将 Genegic 接口添加到服务中。这段代码是如何工作的?

Add Genegic interface into service. How does this code work?

我正在尝试在我的 Dotnet 核心项目中实施存储库和工作单元。

我有这样一行代码:

 services.AddScoped(typeof(IEfRepository<>), typeof(EfRepository<>));
public interface IEfRepository<TEntity> where TEntity : class
    {
        /// <summary>
        /// SingleOrDefault expression
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        Task<TEntity> SingleOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);
...

并实施:

 public class EfRepository<TEntity> : IEfRepository<TEntity> where TEntity : class
    {
        /// <summary>
        /// Fields
        /// </summary>
        private readonly DbContext _dbContext;
        private DbSet<TEntity> _entities;

        /// <summary>
        /// Initialize a new instance of the <see cref=" EfRepository{TEntity}"/> class
        /// </summary>
        /// <param name="dbContext"></param>
        public EfRepository(DbContext dbContext)
        {
            _dbContext = dbContext;
        }

当调解员发送请求时。它在 Handler class 中处理,服务从构造函数中注入:

public class KiemtracongtrinhQueryHandler : IRequestHandler<GetKiemtracongtrinhQuery, GKiemtracongtrinhDto>,
                                                IRequestHandler<ListKiemtracongtrinhQuery, IEnumerable<GKiemtracongtrinhDto>>
    {

        private readonly IGKiemtracongtrinhRepository _gKiemtracongtrinhRepository;
        private readonly IMapper _mapper;

        /// <summary>
        /// Initialize a new instance of the <see cref="KiemtracongtrinhQueryHandler"/> class
        /// </summary>
        /// <param name="gKiemtracongtrinhRepository"></param>
        /// <param name="mapper"></param>
        public KiemtracongtrinhQueryHandler(IGKiemtracongtrinhRepository gKiemtracongtrinhRepository,
                                            IMapper mapper)
        {
            _gKiemtracongtrinhRepository = gKiemtracongtrinhRepository ?? throw new ArgumentNullException(nameof(gKiemtracongtrinhRepository));
            _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
        }

我认为你是对的。一些修复是:

  1. 在 EfRepository 中 class。
 public class EfRepository<TEntity> : IEfRepository<TEntity> where TEntity : class
    {
        /// <summary>
        /// Fields
        /// </summary>
        private readonly DbContext _dbContext;

        /// <summary>
        /// Initialize a new instance of the <see cref=" EfRepository{TEntity}"/> class
        /// </summary>
        /// <param name="dbContext"></param>
        public EfRepository(DbContext dbContext)
        {
            _dbContext = dbContext;
        }

        /// <summary>
        /// Initialize a new instance of the <see cref=" EfRepository{TEntity}"/> class
        /// </summary>
        /// <param name="dbContext"></param>
        public EfRepository(DbContext dbContext)
        {
            _dbContext = dbContext;
        }
        ///Example method
        public async Task AddItem(T item)
        {
            _context.Set<T>().Add(item);
            return await _context.SaveChangesAsync();
        }
        ///Example method
        public async Task<List<T>> GetAllRecords(T exampleItem)
        {
            return _context.Set<T>().ToList();
        }

我看不出 DbEtities 应该在这里的原因。

2) 您的处理人:

public class KiemtracongtrinhQueryHandler : IRequestHandler<GetKiemtracongtrinhQuery, GKiemtracongtrinhDto>,
                                                IRequestHandler<ListKiemtracongtrinhQuery, IEnumerable<GKiemtracongtrinhDto>>
    {

        private readonly IEfRepository<GKiemtracongtrinhRepository> _gKiemtracongtrinhRepository;
        private readonly IMapper _mapper;

        /// <summary>
        /// Initialize a new instance of the <see cref="KiemtracongtrinhQueryHandler"/> class
        /// </summary>
        /// <param name="gKiemtracongtrinhRepository"></param>
        /// <param name="mapper"></param>
        public KiemtracongtrinhQueryHandler(IEfRepository<GKiemtracongtrinhRepository> gKiemtracongtrinhRepository,
                                            IMapper mapper)
        {
            _gKiemtracongtrinhRepository = gKiemtracongtrinhRepository ?? throw new ArgumentNullException(nameof(gKiemtracongtrinhRepository));
            _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
        }

在处理程序中,您需要传递通用存储库。

如果你想看这个例子:https://github.com/steliosgiakoumidis/NotificationDatabase

关于UnitOfWork,您可以使用它的方式如下:


    public interface IUnitOfWork
    {
        IRepository2 Repository1{ get; }
        IRepository2 Repository2 { get; }
        IRepository3 Repository3 { get; }

        Task<bool> SaveChangesAsync();
    }
 public class UnitOfWork : IUnitOfWork
    {
        public IRepository1 Repository1 { get; }
        public IRepository2 Repository2 { get; }
        public IRepository3 Repository3 { get; }

        private readonly _dbContext;

        public UnitOfWork(IRepository1  repository1, IRepository2 repository2,
            IRepository3 repository3)
        {
            Repository1 = repository1;
            Repository2 = repository2;
            Repository3 = repository3;
        }

        public async Task<bool> SaveChangesAsync()
        {
            try
            {
                await _context.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                Log.Error($"An error occured when saving changes to the database.)
            }
        }
}

最好在 UnitOfWork 中传递 SaveChanges 并在所有数据库操作完成后执行该方法。 SaveChanges 方法通常不在应用层的 database/infrastructure 层调用,而是调用。 使用工作单元可以节省相当多的注射。由于您将所有存储库捆绑到一个 UoW 中,因此您将其注入。

我自己我没有使用过通用 repostiries 和 UoW,但我更喜欢使用抽象 class,但主要思想是相同的。