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

问题描述 投票:0回答:1

我想在我的Dotnet核心项目中实现Repository和Unit Of Work。

我有一行代码是这样的,我想在我的Dotnet核心项目中实现Repository和Unit Of Work。

 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类中处理,服务从contructor注入。

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));
        }
.net .net-core dependency-injection repository-pattern unit-of-work
1个回答
1
投票

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

  1. 在EfRepository类中
 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.comsteliosgiakoumidisNotificationDatabase

关于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方法通常不在应用层的databaseinfrastructure层中调用,而是在应用层中调用。使用工作单元,你可以节省相当多的注入。因为你把所有的仓库都捆绑在一个UoW中,你可以用这个来代替注入。

我自己没有使用过通用的存储库和UoW,但我更喜欢使用一个抽象类来代替,但主要的想法是一样的。

© www.soinside.com 2019 - 2024. All rights reserved.