存储库模式工作单元依赖注入Ninject
Repository Pattern Unit of work Dependency Injection Ninject
我在我的架构中使用存储库、工作单元和依赖注入模式
我的等级:
核心
数据层
业务层
服务层
我的结构有问题,在工作单元中 class 如上所述
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 的实例 class
这是 KullaniciDal
的代码
public interface IKullaniciDal : IRepositoryEntityFramework<Kullanici>
{
}
public class KullaniciDal : RepositoryEntityFramework<Kullanici>, IKullaniciDal
{
public KullaniciDal(IDataContext dbContextBase) : base(dbContextBase)
{
}
}
我想为数据访问层编写一些额外的功能,特别是其中一些功能,并希望将这些实例用作工作单元的一部分 class
我如何注射 Dal classes?
小心我将上下文对象传递给每个 dal class
我在这里看到了几个问题。
首先,您的 UoW 正在更新 DAL 本身,而不是由 DI 注入它。如果您要走 DI 路线,最好让 DI 注入所有内容并让它自己管理对象的范围等。作为一般规则,如果您发现自己将 new() 与基础设施一起使用 class,请退后一步并考虑注入它。
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 时,repository/dll 和工作单元都需要上下文,但它们是不同的模式。我将允许您的 DI 容器适当地确定您的上下文、您的 UoW、您的 BLL 等的范围,并且您无需担心传递依赖项,让容器为您完成工作。
这还有其他 SOLID 设计优势。考虑一下您是否正在实施一个 http 过滤器,该过滤器会自动将您的 uow 提交给 http 会话。过滤器只需要了解 IUnitOfWork 方法提交、回滚等。它应该依赖于最小接口,不需要了解 DAL。
我找到了另一种在需要时即时创建存储库的解决方案。
它还支持多个数据上下文,还有一点是 IUnitOfWork 接口继承了 IDisposable。该代码适用于 EF Core v2.0。这是全部 UnitOfWork.cs class 代码:
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;
}
}
}
}
我在我的架构中使用存储库、工作单元和依赖注入模式 我的等级:
核心
数据层
业务层
服务层
我的结构有问题,在工作单元中 class 如上所述
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 的实例 class 这是 KullaniciDal
的代码 public interface IKullaniciDal : IRepositoryEntityFramework<Kullanici>
{
}
public class KullaniciDal : RepositoryEntityFramework<Kullanici>, IKullaniciDal
{
public KullaniciDal(IDataContext dbContextBase) : base(dbContextBase)
{
}
}
我想为数据访问层编写一些额外的功能,特别是其中一些功能,并希望将这些实例用作工作单元的一部分 class
我如何注射 Dal classes? 小心我将上下文对象传递给每个 dal class
我在这里看到了几个问题。
首先,您的 UoW 正在更新 DAL 本身,而不是由 DI 注入它。如果您要走 DI 路线,最好让 DI 注入所有内容并让它自己管理对象的范围等。作为一般规则,如果您发现自己将 new() 与基础设施一起使用 class,请退后一步并考虑注入它。
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 时,repository/dll 和工作单元都需要上下文,但它们是不同的模式。我将允许您的 DI 容器适当地确定您的上下文、您的 UoW、您的 BLL 等的范围,并且您无需担心传递依赖项,让容器为您完成工作。
这还有其他 SOLID 设计优势。考虑一下您是否正在实施一个 http 过滤器,该过滤器会自动将您的 uow 提交给 http 会话。过滤器只需要了解 IUnitOfWork 方法提交、回滚等。它应该依赖于最小接口,不需要了解 DAL。
我找到了另一种在需要时即时创建存储库的解决方案。 它还支持多个数据上下文,还有一点是 IUnitOfWork 接口继承了 IDisposable。该代码适用于 EF Core v2.0。这是全部 UnitOfWork.cs class 代码:
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;
}
}
}
}