سلام خدمت استاد عزیز و همه دوستان
برای جلوگیری از ایجاد کدهای تکراری جنریک ریپوزیتوری من به این صورت عمل کرده ام.
کدهای 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<>));
امیدوارم براتون مفید بوده باشه و در صورتی که مشکلی یا باگی داره نظرتون رو بفرمایید.
با تشکر