具有工作单元或ActiveRecord的存储库模式的紧密对齐程度

时间:2009-10-15 14:32:50

标签: entity-framework repository-pattern unit-of-work

虽然我没有做全面的DDD,但我发现存储库模式很有吸引力,我确实试图沿着聚合根边界对存储库进行细分。我正在实体框架之上实现存储库,这里ObjectContext允许工作单元样式,因为它跟踪实体的更改,并在调用SaveChanges时生成适当的SQL。

我正在努力解决我的存储库中两种不同的方法,即何时调用SaveChanges - 差别似乎在于我是采用工作单元还是主动记录语义。如果我将存储库接口定义如下:

public interface IRepository<T>
{
    T Get(int id);
    IList<T> GetAll();
    IQueryable<T> Query();
    void Delete(T entity);
    void Add(T entity);
    IUnitOfWork GetUnitOfWork();
}

和IUnitOfWork

public interface IUnitOfWork
{
    void SaveChanges();
}

然后在Add(T实体)实现中,我似乎有两个选择:

    public void Add(Document entity)
    {
        DB.AddToDocumentSet(entity);
        GetUnitOfWork().SaveChanges();  //delegates to the ObjectContext's SaveChanges
    }

    public void Add(Document entity)
    {
        DB.AddToDocumentSet(entity);
    }

在前一种情况下,存储库的Add方法是在每个操作上发送SQL。在后一种情况下,调用代码负责从存储库中获取工作单元并在其认为合适时调用SaveChanges。这允许工作单元跨越不同的存储库(我确保每个存储库在其构造中获得相同的工作单元)。

我的直觉是第二种方法更灵活。采用工作单元模式还意味着对实体的更新更好一点,因为调用代码只是更新存储库返回的实体的属性,然后调用UnitOfWork.SaveChanges。

使用存储库模式时,一种方法通常比其他方法更受青睐吗?

1 个答案:

答案 0 :(得分:2)

这取决于您未提及的故障模式要求。这主要是如何处理工作单元中发生的故障的问题。您基本上有两种选择,尽管还有其他更复杂的变体:

  1. 保存在工作单元期间发生的所有更改,直至失败。
  2. 回滚由于失败而在工作单元期间发生的所有更改。
  3. 您的第一个Add方法更适合方案1,而您的第二个Add方法更适合方案2。

    方案1可能需要智能应用程序代码以允许用户在故障点恢复。方案2在应用程序方面更容易实现,但如果用户失败,则可能会使用户感到沮丧,例如,进入9步骤的8个步骤。