CRUD Operations in ASP.NET Core with 3-Tier Harmony and Command Builder Design Pattern

Command Builder Design Pattern in an ASP.NET Core Web API using a Three-Tier Architecture for CRUD operations. For the sake of this example, let's assume you have a model named CSharpCornerArticle.

Three-Tier Architecture Overview

  1. Presentation Layer (Controller): Handles incoming HTTP requests, processes input data, and interacts with the service layer.
  2. Business Logic Layer (Service): Contains business logic, validates data, and coordinates the interaction between the presentation and data access layers.
  3. Data Access Layer (Repository): Manages data storage, retrieval, and manipulation.

Model - CSharpCornerArticle

// Sardar Mudassar Ali Khan
public class CSharpCornerArticle
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    // Add other properties as needed
}

Data Access Layer (Repository)

//Sardar Mudassar Ali Khan
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;

public interface ICSharpCornerArticleRepository
{
    CSharpCornerArticle GetById(int id);
    IEnumerable<CSharpCornerArticle> GetAll();
    void Add(CSharpCornerArticle article);
    void Update(CSharpCornerArticle article);
    void Delete(int id);
}

public class CSharpCornerArticleRepository : ICSharpCornerArticleRepository
{
    private readonly YourDbContext _dbContext; // Replace YourDbContext with your actual DbContext class

    public CSharpCornerArticleRepository(YourDbContext dbContext)
    {
        _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
    }

    public CSharpCornerArticle GetById(int id)
    {
        return _dbContext.CSharpCornerArticles.Find(id);
    }

    public IEnumerable<CSharpCornerArticle> GetAll()
    {
        return _dbContext.CSharpCornerArticles.ToList();
    }

    public void Add(CSharpCornerArticle article)
    {
        _dbContext.CSharpCornerArticles.Add(article);
        _dbContext.SaveChanges();
    }

    public void Update(CSharpCornerArticle article)
    {
        _dbContext.Entry(article).State = EntityState.Modified;
        _dbContext.SaveChanges();
    }

    public void Delete(int id)
    {
        var article = _dbContext.CSharpCornerArticles.Find(id);
        if (article != null)
        {
            _dbContext.CSharpCornerArticles.Remove(article);
            _dbContext.SaveChanges();
        }
    }
}

Business Logic Layer (Service)

// Sardar Mudassar Ali Khan
public interface ICSharpCornerArticleService
{
    CSharpCornerArticle GetArticleById(int id);
    IEnumerable<CSharpCornerArticle> GetAllArticles();
    void AddArticle(CSharpCornerArticle article);
    void UpdateArticle(CSharpCornerArticle article);
    void DeleteArticle(int id);
}

public class CSharpCornerArticleService : ICSharpCornerArticleService
{
    private readonly ICSharpCornerArticleRepository _repository;

    public CSharpCornerArticleService(ICSharpCornerArticleRepository repository)
    {
        _repository = repository ?? throw new ArgumentNullException(nameof(repository));
    }

    public CSharpCornerArticle GetArticleById(int id)
    {
        return _repository.GetById(id);
    }

    public IEnumerable<CSharpCornerArticle> GetAllArticles()
    {
        return _repository.GetAll();
    }

    public void AddArticle(CSharpCornerArticle article)
    {
        if (article == null)
        {
            throw new ArgumentNullException(nameof(article));
        }

        _repository.Add(article);
    }

    public void UpdateArticle(CSharpCornerArticle article)
    {
        if (article == null)
        {
            throw new ArgumentNullException(nameof(article));
        }

        _repository.Update(article);
    }

    public void DeleteArticle(int id)
    {
        _repository.Delete(id);
    }
}

Presentation Layer (Controller)

// Sardar Mudassar Ali Khan
[ApiController]
[Route("api/csharpcornerarticles")]
public class CSharpCornerArticleController : ControllerBase
{
    private readonly ICSharpCornerArticleService _articleService;

    public CSharpCornerArticleController(ICSharpCornerArticleService articleService)
    {
        _articleService = articleService;
    }

    [HttpGet("{id}")]
    public ActionResult<CSharpCornerArticle> Get(int id)
    {
        var article = _articleService.GetArticleById(id);

        if (article == null)
        {
            return NotFound();
        }

        return article;
    }

    [HttpGet]
    public ActionResult<IEnumerable<CSharpCornerArticle>> Get()
    {
        var articles = _articleService.GetAllArticles();
        return Ok(articles);
    }

    [HttpPost]
    public ActionResult Post([FromBody] CSharpCornerArticle article)
    {
        _articleService.AddArticle(article);
        return Ok();
    }

    [HttpPut("{id}")]
    public ActionResult Put(int id, [FromBody] CSharpCornerArticle article)
    {
        var existingArticle = _articleService.GetArticleById(id);

        if (existingArticle == null)
        {
            return NotFound();
        }

        article.Id = id;
        _articleService.UpdateArticle(article);

        return Ok();
    }

    [HttpDelete("{id}")]
    public ActionResult Delete(int id)
    {
        var existingArticle = _articleService.GetArticleById(id);

        if (existingArticle == null)
        {
            return NotFound();
        }

        _articleService.DeleteArticle(id);

        return Ok();
    }
}

In this example, the CSharpCornerArticleController acts as the presentation layer, the CSharpCornerArticleService as the business logic layer, and the CSharpCornerArticleRepository as the data access layer. You can replace the repository implementation with Entity Framework or any other data access mechanism as per your requirements.

This is a basic example, and you might need to adapt it to fit your specific needs, especially in terms of error handling, validation, and other aspects depending on your application's requirements.

Conclusion

The provided example demonstrates the implementation of a Three-Tier Architecture in an ASP.NET Core Web API for CRUD operations on a model named CSharpCornerArticle. Here's a summary of the key components:

Model (CSharpCornerArticle)

  1. Represents the data structure with properties like ID, Title, and Content.
  2. Data Access Layer (Repository):

Interface ICSharpCornerArticleRepository defines methods for data operations.

Class CSharpCornerArticleRepository implements the repository, interacting with the data storage (e.g., a database) using technologies like Entity Framework.

Business Logic Layer (Service)

Interface ICSharpCornerArticleService declares methods representing the business logic.
Class CSharpCornerArticleService implements these methods, coordinating with the repository and adding any necessary business logic.

Presentation Layer (Controller)

  1. CSharpCornerArticleController is an API controller responsible for handling HTTP requests.
  2. It interacts with the service layer (ICSharpCornerArticleService) to perform CRUD operations.
  3. This architecture promotes separation of concerns, making the codebase modular and maintainable. Each layer has a distinct responsibility:
  4. The Presentation Layer handles incoming requests and orchestrates interactions with the service layer.
  5. The Business Logic Layer contains application-specific logic and ensures that data operations adhere to business rules.
  6. The Data Access Layer manages interactions with the data storage, abstracting away the details of the storage mechanism.

This design supports scalability and maintainability by allowing changes in one layer without affecting others. It's important to note that this is a basic example, and in a real-world scenario, you may need to consider aspects like validation, error handling, security, and scalability based on your application's requirements.


Similar Articles