• 1405/04/03

تمرین جلسه 78 راه حل مشکل کد تکراری جنریک ریپوزیتوری :

سلام خدمت استاد عزیز و همه دوستان

برای جلوگیری از ایجاد کدهای تکراری جنریک ریپوزیتوری من به این صورت عمل کرده ام.

کدهای IGenericRepository

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;

namespace ShopStock.Domain.Contracts
{
    public interface IGenericRepository<T> where T:class
    {

        void Create(T entity);

        IEnumerable<T> GetAll();


        Task<List<T>> GetAllAsync();


        T? GetEntityByPk(object obj);


        Task<T?> GetEntityByPkAsync(object obj);


        bool Delete(T entity);


        bool Delete(object obj);


        int Save();


        Task<int> SaveAsync();


        T? Select(Expression<Func<T, bool>> where);


        Task<T?> SelectAsync(Expression<Func<T, bool>> where);


        void Update(T entity);


        Task<bool> IsExistByPkAsync(object obj);
       


    }
}

 

کدهای GenericRepository.cs : 

using ShopStock.Domain.Contracts;
using Microsoft.EntityFrameworkCore;
using ShopStock.Infra.Data.Context;
using System.Linq.Expressions;


namespace ShopStock.Infra.Data.Repositories
{
    public class GenericRepository<T>: IGenericRepository<T> where T : class
    {
        private readonly EshopDbContext _context;
        private readonly DbSet<T> _dbSet;

        public GenericRepository(EshopDbContext context)
        {
            _context = context;
            _dbSet = _context.Set<T>();
        }

        public void Create(T entity)
        {
            _dbSet.Add(entity);
        }

        public IEnumerable<T> GetAll()
        {
            return _dbSet;
        }

        public async Task<List<T>> GetAllAsync()
        {
            return await _dbSet.ToListAsync();
        }

        public T? GetEntityByPk(object obj)
        {
            return _dbSet.Find(obj);
        }

        public async Task<T?> GetEntityByPkAsync(object obj)
        {
            return await _dbSet.FindAsync(obj);
        }

        public bool Delete(T entity)
        {
            try
            {
                _dbSet.Remove(entity);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool Delete(object obj)
        {
            try
            {
                T? entity = GetEntityByPk(obj);
                if (entity != null)
                    return this.Delete(entity);
                return false;
            }
            catch
            {
                return false;
            }
        }

        public int Save()
        {
            return _context.SaveChanges();
        }

        public Task<int> SaveAsync()
        {
            return _context.SaveChangesAsync();
        }

        public T? Select(Expression<Func<T, bool>> where)
        {
            return _dbSet.SingleOrDefault(where);
        }

        public async Task<T?> SelectAsync(Expression<Func<T, bool>> where)
        {
            return await _dbSet.SingleOrDefaultAsync(where);
        }

        public void Update(T entity)
        {
            _context.Update(entity);
        }

        public async Task<bool> IsExistByPkAsync(object obj)
        {
            var result = await _dbSet.FindAsync(obj);
            return  result != null;
        }
    }
}

 

 

برای مدل هایی که متدهای ریپوزیتوری مخصوص به خودشون رو دارن (مثلا Product) اینترفیس خودشون رو میسازیم

کدهای IProductRepository.cs : 

using ShopStock.Domain.Models.Products;
using System;
using System.Collections.Generic;
using System.Text;

namespace ShopStock.Domain.Contracts.ProductRepository
{
    public interface IProductRepository
    {

        Task<Product?> GetProductByIdWithIncludesAsync(int productId);

        Product? GetProductByIdWithIncludes(int productId);

        Task<bool> IsExistProductBySlugAsync(string slug);


    }
}

 

 

 

 

 

کدهای ProductRepository.cs : 

using Microsoft.EntityFrameworkCore;
using ShopStock.Domain.Contracts.ProductRepository;
using ShopStock.Domain.Models.Products;
using ShopStock.Infra.Data.Context;


namespace ShopStock.Infra.Data.Repositories.ProductRepository
{
    public class ProductRepository(EshopDbContext _context) :IProductRepository
    {

        public async Task<Product?> GetProductByIdWithIncludesAsync(int productId)
        {
            return await _context.Products
                .AsSplitQuery()
                .Include(x => x.User)
                .Include(x => x.ProductBrand)
                .SingleOrDefaultAsync(x => x.Id == productId);

        }


        public Product? GetProductByIdWithIncludes(int productId)
        {
            return _context.Products
                .AsSplitQuery()
                .Include(x => x.User)
                .Include(x => x.ProductBrand)
                .SingleOrDefault(x => x.Id == productId);
        }

        public async Task<bool> IsExistProductBySlugAsync(string slug)
        {
            return await _context.Products.IgnoreQueryFilters().AnyAsync(x => x.Slug == slug);
        }

    }
}


 

 

 

 

 

کدهای سرویس ProductService.cs  (با این فرض که فعلا از IProductService ارث بری نشده)

using ShopStock.Domain.Contracts;
using ShopStock.Domain.Contracts.ProductRepository;
using ShopStock.Domain.Models.Products;



namespace ShopStock.Application.Services.Implementation.ProductImp
{
    public class ProductService
    {
        private readonly IProductRepository _productRepository;
        private readonly IGenericRepository<Product> _genericRepository;
        public ProductService(IProductRepository productRepository, IGenericRepository<Product> genericRepository)
        {
            _productRepository = productRepository;
            _genericRepository = genericRepository;
        }
      
       
    }
}

 

 

 

 

البته این قطعه کد هم باید به IOC اصافه بشه :

            services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));

 

امیدوارم براتون مفید بوده باشه و در صورتی که مشکلی یا باگی داره نظرتون رو بفرمایید.

با تشکر