1

因此,通常在实现此模式时,我先使用Service然后Repository<Type>让存储库使用UnitOfWork.

我正在玩弄一个方法UnitOfWorkRepository<Type>就像这样:

public class UnitOfWork : IUnitOfWork
{
    public IRepository<TEntity> GetRepository<TEntity>() where TEntity : Core.Domain.Model.EntityBase<TEntity>
    {
        return new Repository<TEntity>(this);
    }
}

然后Service将采用UnitOfWork并可以从中解决所需的存储库。

你怎么看?你觉得这有什么缺陷吗?

4

1 回答 1

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

您是对的,这使得服务可以轻松地解析其存储库,而无需将它们单独传递给构造函数,这在您可能在单个服务中使用多个存储库(例如采购订单和产品)的情况下很有用。

使用这种与 ORM 无关的接口的一个好处是,它意味着您可以轻松地切换 ORM。老实说,我从实体框架更改为另一个 ORM 的机会很小,但事实是,如果需要,我可以。作为奖励,我的服务更容易测试,而且我还发现这使我的服务类更干净,因为它现在完全不知道正在使用的 ORM,并且完全针对上面的两个接口工作。

关于关于通用存储库接口的评论,我的建议是务实,做最适合您和您的应用程序的事情。在 Stackoverflow 上有很多关于这个主题的问题,他们的答案各不相同,关于哪种是最好的方法(EG 暴露IQueryablevs IEnumerable,通用 vs 非通用)。

我玩弄没有通用存储库,因为您可能已经注意到我的IRepository界面看起来像IDbSet;我采用这种方法的原因是它允许我的实现处理您使用DbContextEG执行的所有 Entity Framework 实体状态管理内容

public void Delete(TEntity entity)
{
    if (Context.Entry(entity).State == EntityState.Detached)
    {
        EntitySet.Attach(entity);
    }
    EntitySet.Remove(entity);
}

If I used IDbSet I would need to perform this in my service layer, which would then require a dependency on DbContext which seemed a much more leaky abstraction than my generic repository.

于 2013-04-24T21:22:24.790 回答