19

在阅读了大量文章后,我仍然不确定与存储库交互时工作单元模式的职责。

存储库负责加载和保存聚合根实体,因此请考虑以下示例代码:

using(IUnitOfWork uow = container.CreateUnitOfWork())
{
     Repository<ARoot> roots = container.GetRepository<ARoot>();
     ARoot root = root.FindByName("ARoot");
     root.Name = "ANewName";

     roots.Save(root);
     uow.Commit();
}

工作单元接口将使用以下方法定义:

public interface IUnitOfWork
{
     void Insert(object);
     void Update(object);        
     void Delete(object);
     void Commit();
     void Rollback();
}

假设存储库是使用非常简单的 SQL 映射器实现的,因此 FindByName 包含一些直接返回 ARoot 的 SQL,Save 实现看起来像这样:

public void Save(T entity)
{
      IUnitOfWork uow = GetUnitOfWork();
      // Tell the UOW we are updating this entity
      uow.Update(entity);
}

然后,工作单元提交代码将构造所有必需的 SQL 以将实体映射回数据库?

问题2)

如果我将聚合根添加到工作单元中,工作单元是负责持久化根及其子实体,还是应该是存储库的 Save 方法将更改的实体添加到工作单元中?例如

public void Save(T entity)
{
      IUnitOfWork uow = GetUnitOfWork();
      // Tell the UOW we are updating this entity
      uow.Update(entity);
      uow.Update(entity.AChildObject);
}

或者......或者

工作单元是否只处理聚合根,并在提交时为其更改集中的每个对象调用存储库 Save 方法,保留 SQL 映射代码以将实体持久存储在存储库中,将第一个代码示例更改为

using(IUnitOfWork uow = container.CreateUnitOfWork())
{
     Repository<ARoot> roots = container.GetRepository<ARoot>();
     ARoot root = root.FindByName("ARoot");
     root.Name = "ANewName";

     //roots.Save(root);
     uow.Update(root);
     // and commit
     uow.Commit();
}

谢谢,

詹姆士

4

3 回答 3

4

在我们的项目中,我们使用 Repository 的行为就像实体的集合,UnitOfWork 用于跟踪这些实体的更改,并将它们写回数据存储。

如果您使用的是 LinqToSql 或其他一些 OR Mapper,那么它本身很可能实现了 UnitOfWork 模式,因此我们通常只是在自己的 IUnitOfWork 中使用 ORMapper 实例。

我们的存储库接口通常类似于..

  IEnumerable<Order> FindByCustomerId(string customerId);
  void Add(Order order);
  void Remove(Order order);

我们在存储库中没有任何保存方法。如果我们不需要 UnitOfWork,那么 Add/Remove 方法将直接作用于数据存储。

如果我们需要一个 UnitOfWork,那么公共接口类似于......

void Commit();
void Rollback();

存储库具有与 UnitOfWork 的内部接口,因此当我们查询存储库时,UnitOfWork 会跟踪返回的对象以进行更改。commit 方法将更改写回数据存储,rollback 方法只是清除它的更改。

当我们使用 LinqToSql 时,DataContext 负责更改跟踪,在回滚时我们只是实例化一个新的上下文。持久性是跨根及其子级处理的。一个 UnitOfWork 实例在所有存储库之间共享。

当我们不使用 LinqToSql 时,我们会实现自己的 UnitOfWork,也许它会调用 web 服务或其他东西,在这种情况下,我们会使用 EntityBase 类在实体类本身中进行更改跟踪。

我们为每个根都有一个存储库,但有时一个根的子节点本身被用作根,所以我们经常需要像 OrderLineRepository 这样的东西,因为我们的系统中有一个用例,用户想要搜索订单行。

于 2010-02-01T11:18:06.253 回答
3

通常我喜欢看到它完成的方式是 UoW 跟踪通过直接调用 IRepository.Save() 保存的更改。

我也更喜欢将 UoW 代码作为一个方面来处理,并且在与域的交互之外进行处理。这意味着它要么由一些全局命令处理程序处理,要么由 Web 服务代码作为完成请求的一部分来处理。换句话说,开始一个请求会打开一个工作单元,结束它会关闭它。这样,域可以不知道 UoW 及其实现。

提交工作单元是导致通过调用 .Save() 和其他更改方法所做的更改被持久化的原因。UoW 很可能以某种方式跟踪这些变化。

于 2011-06-25T23:58:45.190 回答
2
  • UnitOfWork 是您的事务处理程序
  • 存储库正在执行将对象加载/保存到数据存储的实际工作

我使用类似于以下的定义:

IUnitOfWork { Commit(); }
IRepository { GetAll(); GetById(); Add(T item); Remove(T item); }

我不会让 UnitOfWork 创建 SQL - 该逻辑将在您的存储库中。您使用的是什么数据存储?

于 2011-06-29T09:07:10.610 回答