简体   繁体   English

Repository Pattern 工作单元依赖注入 Ninject

[英]Repository Pattern Unit of work Dependency Injection Ninject

I use repository, unit of work and dependency injection patterns in my architecture My tiers :我在我的架构中使用存储库、工作单元和依赖注入模式我的层:

Core

DataLayer数据层

BusinessLayer业务层

ServiceLayer服务层

There is something wrong in my structure, in unit of work class as above我的结构有问题,在上面的工作类单元中

   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();
    }
}

here i want to inject DataAccessLayers like _kullaniciDAL在这里我想注入像 _kullaniciDAL 这样的 DataAccessLayers

searched a lot and i saw some examples for generating repository genericly bu i dont want to access the repository instance directly from business, i want to access the instances of my KullaniciDal class Here is the code of KullaniciDal搜索了很多,我看到了一些生成存储库的示例,但我不想直接从业务中访问存储库实例,我想访问我的 KullaniciDal 类的实例这里是 KullaniciDal 的代码

 public interface IKullaniciDal : IRepositoryEntityFramework<Kullanici>
{
}

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

I want to write some extra functions to data access layer in special to some of them and want to use the instances as a part of unit of work class我想写一些额外的函数到数据访问层,特别是其中一些,并希望将实例用作工作单元的一部分

How can i inject Dal classes?我如何注入 Dal 类? Be carefull that i pass context object to every dal class小心我将上下文对象传递给每个 dal 类

There's a couple issues I see here.我在这里看到了几个问题。

First, your UoW is newing up the DAL itself rather than having it injected by DI.首先,您的 UoW 正在更新 DAL 本身,而不是由 DI 注入它。 If you're going the DI route you're better off just letting the DI inject everything and let it manage the scope of the objects etc by itself.如果你要走 DI 路线,你最好让 DI 注入一切,让它自己管理对象的范围等。 As sort of a general rule, if you find yourself using new() with an infrastructure class, take a step back and consider injecting it.作为一般规则,如果您发现自己将 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();
    }
}

The next question is more of a design question.下一个问题更像是一个设计问题。 Why are all of these DALs needed by the UoW?为什么 UoW 需要所有这些 DAL? I find this odd myself.我自己觉得这很奇怪。

If I was implementing a business layer that needed to control the UoW and a DAL, I would simply inject them into the business layer.如果我要实现一个需要控制 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
    }

}

It's true that the Context is required by both the repository/dll and the unit of work when using an ORM such as EF, but they are seperate patterns.确实,在使用诸如 EF 之类的 ORM 时,存储库/dll 和工作单元都需要上下文,但它们是单独的模式。 I would allow your DI container to scope both your context, your UoW, your BLL etc all appropriately and you won't need to worry about passing dependencies around, let the container do the work for you.我将允许您的 DI 容器适当地限定您的上下文、您的 UoW、您的 BLL 等范围,您无需担心传递依赖项,让容器为您完成工作。

This has other SOLID design benefits as well.这还有其他 SOLID 设计优势。 Consider if you are implementing say an http filter that auto-commits your uow with the http session.考虑一下您是否正在实施一个 http 过滤器,该过滤器通过 http 会话自动提交您的 uow。 The filter only needs to know about the IUnitOfWork methods commit, rollback etc. It should depend on that minimum interface, it doesn't need to know about the DALs.过滤器只需要知道 IUnitOfWork 方法提交、回滚等。它应该依赖于那个最小接口,它不需要知道 DAL。

I found another solution for creating repositories on the fly when it is needed.我找到了另一种在需要时即时创建存储库的解决方案。 It also supports mutliple data contexes and there is one more point that IUnitOfWork interface inherites IDisposable.它还支持多个数据上下文,还有一点是 IUnitOfWork 接口继承了 IDisposable。 The code is for EF Core v2.0.该代码适用于 EF Core v2.0。 Here is the all UnitOfWork.cs class code :这是所有 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;
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM