Create a web API using .NET Core 7 with the Unit of Work pattern and a generic repository.

Here’s an example of how you can create a web API using .NET Core 7 with the Unit of Work pattern and a generic repository.

First, let’s define the generic repository and the unit of work:

// Generic Repository Interface
public interface IRepository<TEntity> where TEntity : class
{
    TEntity GetById(int id);
    IEnumerable<TEntity> GetAll();
    void Add(TEntity entity);
    void Update(TEntity entity);
    void Delete(TEntity entity);
}

// Unit of Work Interface
public interface IUnitOfWork : IDisposable
{
    IRepository<TEntity> GetRepository<TEntity>() where TEntity : class;
    void SaveChanges();
}

Next, we’ll implement the generic repository and the unit of work:

// Generic Repository Implementation
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
    private DbContext _context;
    private DbSet<TEntity> _dbSet;

    public Repository(DbContext context)
    {
        _context = context;
        _dbSet = context.Set<TEntity>();
    }

    public TEntity GetById(int id)
    {
        return _dbSet.Find(id);
    }

    public IEnumerable<TEntity> GetAll()
    {
        return _dbSet.ToList();
    }

    public void Add(TEntity entity)
    {
        _dbSet.Add(entity);
    }

    public void Update(TEntity entity)
    {
        _dbSet.Update(entity);
    }

    public void Delete(TEntity entity)
    {
        _dbSet.Remove(entity);
    }
}

// Unit of Work Implementation
public class UnitOfWork : IUnitOfWork
{
    private DbContext _context;
    private Dictionary<Type, object> _repositories;

    public UnitOfWork(DbContext context)
    {
        _context = context;
        _repositories = new Dictionary<Type, object>();
    }

    public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
    {
        if (!_repositories.ContainsKey(typeof(TEntity)))
        {
            var repository = new Repository<TEntity>(_context);
            _repositories.Add(typeof(TEntity), repository);
        }

        return (IRepository<TEntity>)_repositories[typeof(TEntity)];
    }

    public void SaveChanges()
    {
        _context.SaveChanges();
    }

    public void Dispose()
    {
        _context.Dispose();
    }
}

Now, let’s create a sample entity and a web API controller that uses the unit of work and repository:

// Sample Entity
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    // other properties
}

// Web API Controller
[ApiController]
[Route("api/products")]
public class ProductsController : ControllerBase
{
    private IUnitOfWork _unitOfWork;
    private IRepository<Product> _productRepository;

    public ProductsController(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
        _productRepository = _unitOfWork.GetRepository<Product>();
    }

    // GET api/products
    [HttpGet]
    public IActionResult Get()
    {
        var products = _productRepository.GetAll();
        return Ok(products);
    }

    // GET api/products/{id}
    [HttpGet("{id}")]
    public IActionResult Get(int id)
    {
        var product = _productRepository.GetById(id);
        if (product == null)
        {
            return NotFound();
        }
        return Ok(product);
    }

    // POST api/products
    [HttpPost]
    public IActionResult Post([FromBody] Product product)
    {
        if (product == null)
        {
            return BadRequest();
        }

        _productRepository.Add(product);
        _unitOfWork.SaveChanges();

        return CreatedAtAction(nameof(Get), new { id = product.Id }, product);
    }

    // PUT api/products/{id}
    [HttpPut("{id}")]
    public IActionResult Put(int id

, [FromBody] Product product)
    {
        if (product == null || id != product.Id)
        {
            return BadRequest();
        }

        var existingProduct = _productRepository.GetById(id);
        if (existingProduct == null)
        {
            return NotFound();
        }

        existingProduct.Name = product.Name;
        // update other properties

        _productRepository.Update(existingProduct);
        _unitOfWork.SaveChanges();

        return NoContent();
    }

    // DELETE api/products/{id}
    [HttpDelete("{id}")]
    public IActionResult Delete(int id)
    {
        var product = _productRepository.GetById(id);
        if (product == null)
        {
            return NotFound();
        }

        _productRepository.Delete(product);
        _unitOfWork.SaveChanges();

        return NoContent();
    }
}

In this example, we have a Product entity, and we create a web API controller named ProductsController. The controller receives an instance of IUnitOfWork in its constructor, which provides access to the unit of work and the generic repository.

Within the controller actions, we use the repository methods to perform CRUD operations on the Product entity. The unit of work manages the transaction and ensures that changes are saved atomically.

Leave a Reply

Your email address will not be published. Required fields are marked *