简体   繁体   中英

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

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

 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? Be carefull that i pass context object to every dal class

There's a couple issues I see here.

First, your UoW is newing up the DAL itself rather than having it injected by 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. As sort of a general rule, if you find yourself using new() with an infrastructure class, take a step back and consider injecting it.

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? 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.

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. 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.

This has other SOLID design benefits as well. Consider if you are implementing say an http filter that auto-commits your uow with the http session. 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.

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. The code is for EF Core v2.0. Here is the all UnitOfWork.cs class code :

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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