因此,通常在实施此模式时,我Service
接受Repository<Type>
,然后让存储库获取UnitOfWork
。
我正在玩UnitOfWork
方法,而Repository<Type>
就像这样:
public class UnitOfWork : IUnitOfWork
{
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : Core.Domain.Model.EntityBase<TEntity>
{
return new Repository<TEntity>(this);
}
}
然后Service
会占用UnitOfWork
并可以解析所需的存储库。
答案 0 :(得分:2)
我在ASP.NET MVC程序中使用了类似的方法,到目前为止它运行良好。
我的IUnitOfWork
界面如下所示:
public interface IUnitOfWork
{
IRepository<TEntity> GetRepositoryFor<TEntity>() where TEntity : class;
void SaveChanges();
}
,关联的IRepository
界面如下所示:
public interface IRepository<TEntity> : IQueryable<TEntity> where TEntity : class
{
TEntity Find(params object[] keyValues);
void Insert(TEntity entity);
void Update(TEntity entity);
void Delete(TEntity entity);
}
然后将其传递给我的服务:
public abstract class BaseService
{
public BaseService(IUnitOfWork unitOfWork)
{
// etc...
}
}
这是对的,这使服务很容易解析它的存储库,而不必将它们单独传递给构造函数,这在您可以在单个服务中使用多个存储库的情况下很有用(EG采购订单和产品)
使用这样的ORM无关接口的一个好处是,它意味着您可以轻松切换ORM。老实说,我从实体框架转换到另一个ORM的机会很小,但事实是,如果需要,我可以。作为奖励我的服务更容易测试,我也发现这使我的服务类更清洁,因为它现在完全不知道正在使用的ORM,并完全反对上面的两个接口。
关于通用存储库界面的评论,我的建议是务实,做最适合您和您的应用程序的方法。关于Stackoverflow在这个主题上有很多问题,对它们的回答差别很大,哪个是最好的方法(EG公开IQueryable
vs IEnumerable
,Generic vs non-generic)。< / p>
我玩而不是拥有通用存储库,因为您可能已经注意到我的IRepository
界面看起来像IDbSet
;我使用此方法的原因是它允许我的实现处理您使用DbContext
E.G。
public void Delete(TEntity entity)
{
if (Context.Entry(entity).State == EntityState.Detached)
{
EntitySet.Attach(entity);
}
EntitySet.Remove(entity);
}
如果我使用IDbSet
,我需要在我的服务层执行此操作,这将需要依赖DbContext
,这似乎比我的通用存储库更具漏洞。