工作单元和存储库模式之间的交互

发布于 2024-08-18 13:02:51 字数 1618 浏览 10 评论 0原文

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

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

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 包含一些直接的信息SQL 返回 ARoot,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);
}

或... 或者,

工作单元是否仅处理聚合根,并且在提交时调用存储库为其更改集中的每个对象保存方法,保留 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();
}

谢谢

詹姆斯的

After reading thorugh plenty of articles I am still unsure about the responsibilities of Unit of Work pattern when interacting with repositories.

Repositories are responsible for loading and saving Aggregate root entities, so consider the following example code:

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

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

The unit of work interface would be defined with the following methods:

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

Lets say the repository is implemented using a very straightforward SQL Mapper, so the FindByName contains some direct SQL to return ARoot, would the Save implementation look something like this:

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

The Unit Of Work Commit code would then construct all the required SQL to map the entity back into the DB?

Question 2)

If I add an aggregate root into the Unit of work, is the unit of work responsible for persisiting the root, and its child enitities, or should be the Save method of the repository add the changed entities into the Unit Of Work? 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

Does a Unit of work only deal with aggregate roots, and when commited calls the repository Save methods for each object in its change set, keeping the SQL mapping code to persist the entity in the Repository, changing the first code example to

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();
}

Thanks,

James

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

旧城烟雨 2024-08-25 13:02:52

在我们的项目中,我们使用存储库来表现得就像实体的集合,而工作单元用于跟踪这些实体的更改,并将它们写回数据存储。

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

我们的存储库界面通常类似于......

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

我们在存储库中没有任何保存方法。如果我们不需要工作单元,则添加/删除方法将直接作用于数据存储。

如果我们需要一个 UnitOfWork,那么公共接口就像...

void Commit();
void Rollback();

存储库有一个与 UnitOfWork 的内部接口,因此当我们查询存储库时,UnitOfWork 会跟踪返回的对象是否发生更改。提交方法将更改写回数据存储,回滚方法只是清除其更改。

当我们使用 LinqToSql 时,DataContext 负责更改跟踪,在回滚时我们只需实例化一个新的 Context。持久性是通过根及其子节点来处理的。所有存储库之间共享一个 UnitOfWork 实例。

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

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

In our project we use a Repository to behave just like a collection of Entities, and the UnitOfWork is used to track the changes on those entities, and for writing them back to the data store.

If you're using LinqToSql or some other OR Mapper, then that is likely to implement a UnitOfWork pattern in itself, so often we just the ORMapper instance in our own IUnitOfWork.

Our repository interface is usually something like..

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

We don't have any save method in the Repository. If we don't need a UnitOfWork, then the Add/Remove methods are acting directly on the datastore.

If we need a UnitOfWork, then the public interface is something like...

void Commit();
void Rollback();

The repository has an internal interface with the UnitOfWork, so when we query the repository, the returned objects are tracked by the UnitOfWork for changes. The commit method writes the changes back to the datastore, the rollback method simply clears it's changes.

When we use LinqToSql the DataContext takes care of the change tracking, on Rollback we just instantiate a new Context. Persistence is handled, across the root and its children. One UnitOfWork instance is shared between all the Repositories.

When we don't use LinqToSql, then we implement our own UnitOfWork, maybe it calls a webservice or something, in this case we do change tracking in the entity classes themselves using an EntityBase class.

We have a repository for each root, but sometimes the children of one root are used as roots themselves, so we often need something like an OrderLineRepository, because we have a Use Case in our system were the user wants to search for Order lines.

时间海 2024-08-25 13:02:52

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

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

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

Typically the way I like to see it done is the UoW tracks the changes which are saved by directly calling IRepository.Save().

I also prefer the UoW code to be handled as an aspect and outside of the interactions with the domain. This means it is either handled by some global command handlers or the web services code as part of completing the request. In other words beginning a request opens a unit-of-work, ending it closes it. This way the domain can be ignorant of the UoW and it's implementation.

Committing the unit of work is what then causes the changes made by calling .Save() and other change methods to be persisted. Quite possibly the UoW is what is tracking these changes somehow.

千笙结 2024-08-25 13:02:52
  • UnitOfWork 是您的交易
    处理程序
  • 存储库正在执行
    加载/保存对象的实际工作
    我使用的数据存储

定义类似于:

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

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

  • UnitOfWork is your transaction
    handler
  • Repository is doing the
    acutal work to load/save objects to
    the data store

I use definitions similar to:

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

I wouldn't have the UnitOfWork creating SQL - that logic would be in your Repository. What data store are you using?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文