在阅读了大量文章后,我仍然不确定在与存储库交互时工作单元模式的责任。
存储库负责加载和保存聚合根实体,因此请考虑以下示例代码:
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 Mapper实现存储库,因此FindByName包含一些直接SQL来返回ARoot,Save实现是否会像这样:
public void Save(T entity)
{
IUnitOfWork uow = GetUnitOfWork();
// Tell the UOW we are updating this entity
uow.Update(entity);
}
然后,工作单元提交代码将构造所有必需的SQL以将实体映射回数据库?
问题2)
如果我将聚合根添加到工作单元中,工作单元是否负责持久化root用户及其子工具,或者应该是存储库的Save方法将已更改的实体添加到工作单元中? e.g
public void Save(T entity)
{
IUnitOfWork uow = GetUnitOfWork();
// Tell the UOW we are updating this entity
uow.Update(entity);
uow.Update(entity.AChildObject);
}
OR ... Alternativly
工作单元是否仅处理聚合根,并且在提交时调用存储库为其更改集中的每个对象保存方法,保持SQL映射代码将实体持久保存在存储库中,将第一个代码示例更改为< / p>
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();
}
谢谢,
詹姆斯
答案 0 :(得分:3)
在我们的项目中,我们使用Repository的行为就像一个Entities集合,UnitOfWork用于跟踪这些实体的变化,并将它们写回数据存储。
如果你正在使用LinqToSql或其他一些OR Mapper,那么这很可能会在我们自己的IUnitOfWork中实现一个UnitOfWork模式。
我们的存储库界面通常类似于..
IEnumerable<Order> FindByCustomerId(string customerId);
void Add(Order order);
void Remove(Order order);
我们在Repository中没有任何save方法。如果我们不需要UnitOfWork,则添加/删除方法直接作用于数据存储区。
如果我们需要UnitOfWork,那么公共接口就像......
void Commit();
void Rollback();
存储库具有与UnitOfWork的内部接口,因此当我们查询存储库时,UnitOfWork会跟踪返回的对象以进行更改。 commit方法将更改写回数据存储区,rollback方法只是清除它的更改。
当我们使用LinqToSql时,DataContext负责更改跟踪,在Rollback上我们只是实例化一个新的Context。跨越root及其子级处理持久性。一个UnitOfWork实例在所有存储库之间共享。
当我们不使用LinqToSql时,我们实现了自己的UnitOfWork,也许它调用了web服务或其他东西,在这种情况下,我们使用EntityBase类更改了实体类本身的跟踪。
我们有一个每个根的存储库,但有时一个根的子节点本身就被用作root,所以我们经常需要类似OrderLineRepository的东西,因为我们的系统中有一个Use Case,用户想搜索Order线。
答案 1 :(得分:3)
通常我喜欢看它完成的方式是UoW跟踪通过直接调用IRepository.Save()保存的更改。
我也更喜欢将UoW代码作为一个方面处理,并且不在与域的交互之外。这意味着它由一些全局命令处理程序或Web服务代码处理,作为完成请求的一部分。换句话说,开始一个请求打开一个工作单元,结束它关闭它。通过这种方式,域名可以忽略UoW及其实现。
提交工作单元会导致通过调用.Save()和其他更改方法进行更改。 UoW很可能是以某种方式跟踪这些变化的。
答案 2 :(得分:2)
我使用类似于:
的定义IUnitOfWork { Commit(); }
IRepository { GetAll(); GetById(); Add(T item); Remove(T item); }
我不会让UnitOfWork创建SQL - 逻辑将存储在您的存储库中。你在使用什么数据存储?