【问题标题】:Repository Pattern Unit of work Dependency Injection Ninject存储库模式工作单元依赖注入 Ninject
【发布时间】:2016-04-01 12:14:01
【问题描述】:

我在我的架构中使用存储库、工作单元和依赖注入模式 我的等级:

核心

数据层

业务层

服务层

我的结构有问题,在上面的工作单元中

   public class UnitOfWork:IUnitOfWork
{
    private readonly IDataContext _context;
    private IKullaniciDal _kullaniciDal;
    private IKategoriDal _kategoriDal;
    private IUrunDal _urunDal;
    public UnitOfWork(IDataContext context)
    {
        _context = context;
    }

    public IKategoriDal KategoriDal => _kategoriDal ?? (_kategoriDal = new KategoriDal(_context));

    public IKullaniciDal KullaniciDal => _kullaniciDal ?? (_kullaniciDal =  new KullaniciDal(_context));

    public IUrunDal UrunDal => _urunDal ?? (_urunDal = new UrunDal(_context));

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

在这里我想注入像 _kullaniciDAL 这样的 DataAccessLayers

搜索了很多,我看到了一些一般生成存储库的示例,但我不想直接从业务访问存储库实例,我想访问我的 KullaniciDal 类的实例 这是 KullaniciDal 的代码

 public interface IKullaniciDal : IRepositoryEntityFramework<Kullanici>
{
}

public class KullaniciDal : RepositoryEntityFramework<Kullanici>, IKullaniciDal
{
    public KullaniciDal(IDataContext dbContextBase) : base(dbContextBase)
   {
   }
}

我想写一些额外的函数到数据访问层,特别是其中一些函数,并希望将实例用作工作单元类的一部分

如何注入 Dal 类? 小心我将上下文对象传递给每个 dal 类

【问题讨论】:

    标签: c# dependency-injection ninject repository-pattern unit-of-work


    【解决方案1】:

    我在这里看到了几个问题。

    首先,您的 UoW 正在更新 DAL 本身,而不是由 DI 注入。如果您要走 DI 路线,最好让 DI 注入所有内容并让它自己管理对象的范围等。作为一般规则,如果您发现自己在基础设施类中使用 new(),请退后一步考虑注入它。

    public class UnitOfWork:IUnitOfWork
    {
        private readonly IDataContext _context;
        public UnitOfWork(IDataContext context,IKullaniciDal kullaniciDal,IKategoriDal kategoriDal, IUrunDal urunDal)
        {
            KullaniciDal = kullaniciDal;
            KategoriDal = kategoriDal;
            UrunDal = urunDal;
            _context = context;
        }
    
        public IKategoriDal KategoriDal{get;private set;}
    
        public IKullaniciDal KullaniciDal{get;private set;}
    
        public IUrunDal UrunDal{get;private set;}
    
        public void SaveChanges()
        {
            _context.SaveChanges();
        }
    }
    

    下一个问题更像是一个设计问题。为什么 UoW 需要所有这些 DAL?我自己也觉得这很奇怪。

    如果我正在实现需要控制 UoW 和 DAL 的业务层,我只需将它们注入业务层。

    public class FooBLL
    {
        private IKullanicDal _kullanicDal;
        private IUnitOfWork _unitOfWork;
        public FooBLL(IKullanicDal kullanicDal,IUnitOfWork unitOfWork)
        {
            _kullanicDal = kullanicDal;
            _unitOfWork = unitOfWork;
        }
    
        public void FooBusinessMethod()
        {
          _unitOfWork.Begin();
          //do something with dal
          //_unitOfWork.Commit etc
        }
    
    }
    

    在使用 EF 等 ORM 时,存储库/dll 和工作单元确实需要上下文,但它们是单独的模式。我将允许您的 DI 容器适当地确定您的上下文、UoW、BLL 等范围,您无需担心传递依赖关系,让容器为您完成工作。

    这还有其他 SOLID 设计优势。考虑一下您是否正在实施一个 http 过滤器,该过滤器通过 http 会话自动提交您的 uow。过滤器只需要知道 IUnitOfWork 方法提交、回滚等。它应该依赖于那个最小接口,它不需要知道 DAL。

    【讨论】:

    • 我尝试过像您提供的那样,但我有一个问题,即工作单元中的上下文实例和 dal 中的实例不一样。我使用 ninject Bind().To().InRequestScope();我在哪里做错了
    • @OkanSARICA 这一定是您的 ninject 配置中的范围问题,请也发布该代码。
    • 我使用的是 Ninject.Web.Common nuget 包,我卸载了它并安装了 Ninject.Mvc3,问题解决了,很有趣
    • 酷,很高兴你把它整理好了。让该容器为您确定范围。
    【解决方案2】:

    我找到了另一种在需要时动态创建存储库的解决方案。 它还支持多个数据上下文,并且 IUnitOfWork 接口继承了 IDisposable 的另一点。该代码适用于 EF Core v2.0。这是所有 UnitOfWork.cs 类代码:

    public class UnitOfWork<TContext> : IUnitOfWork<TContext> where TContext : DbContext
    {
        private Dictionary<string, dynamic> _repositories;
        private DbContext _context;
    
        public UnitOfWork(TContext context)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context));
        }
    
        public IRepository<TEntity> Repository<TEntity>() where TEntity : class, IEntity, new()
        {
            if (_repositories == null)
            {
                _repositories = new Dictionary<string, dynamic>();
            }
            var type = typeof(TEntity).Name;
            if (_repositories.ContainsKey(type))
            {
                return (IRepository<TEntity>)_repositories[type];
            }
            _repositories.Add(type, Activator.CreateInstance(typeof(RepositoryEntityFramework<TEntity>), _context));
            return _repositories[type];
        }
    
        public void SaveChanges()
        {
            _context.SaveChanges();
        }
    
        public void BeginTransaction(System.Data.IsolationLevel isolationLevel = System.Data.IsolationLevel.ReadCommitted)
        {
            _context.Database.BeginTransaction();
        }
    
        public bool Commit()
        {
            _context.Database.CommitTransaction();
            return true;
        }
    
        public void Rollback()
        {
            _context.Database.RollbackTransaction();
        }
    
        /// <inheritdoc />
        /// <summary>
        /// Disposes the current object
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        /// <summary>
        /// Disposes all external resources.
        /// </summary>
        /// <param name="disposing">The dispose indicator.</param>
        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_context != null)
                {
                    _context.Dispose();
                    _context = null;
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 2014-10-28
      • 2010-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多