工作单元类如何知道提交时调用哪个存储库?

发布于 2024-12-06 04:46:13 字数 398 浏览 0 评论 0原文

* 前言:我对工作单元模式还很陌生 *

我的目标是实现一个工作单元类,它将能够跟踪在给定事务中已更改的所有对象。我读到的有关工作单元模式的所有内容都与存储库模式并存。这就是我想使用的方法。

比如说我创建一个新用户。在我的工作单元对象上,我有一个新创建的对象列表,因此我将新用户添加到此列表中。我的用户存储库有一个名为 Create 的方法,它接受一个 User 并调用一个存储过程将数据添加到数据库中。当我对工作单元调用 commit 时,它如何根据新对象列表知道要调用哪个存储库和方法?假设它包含一个 User 对象和一个 Comment 对象。两者都是新创建的,需要在提交时添加。我不确定如何实现这一点。

有人可以更好地解释这一点吗?如果可能的话,甚至可以举一个小例子吗?

谢谢。

* Preface: I'm pretty new to the unit of work pattern *

My goal is to implement a unit of work class that will be able to keep track of all objects that have been changed throughout a given transaction. Everything I read about the unit of work pattern has it side by side with the repository pattern. So this is the approach I'd like to use.

Say for example I create a new User. On my unit of work object, I have a list of newly created objects, so I add my new User to this list. My user repository has a method titled Create, which takes in a User and calls a stored procedure to add the data to the database. When I call commit on my unit of work, how will it know which repository and method to call based on the list of new objects? Say it contains a User object and a Comment object. Both are newly created and need to be added on commit. I'm uncertain how to accomplish this.

Could somebody explain this a bit better and maybe even a small example if possible?

Thanks.

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

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

发布评论

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

评论(4

|煩躁 2024-12-13 04:46:13

UnitOfWork 是一种已经由 ORM 实现的基础架构模式,就像 身份映射。您不必重新发明轮子。另一方面,存储库是一个域模型的一部分。 Repository 和 UnitOfWork 在不同级别运行。 UnitOfWork 不需要调用 Repository,因为它不知道 Repository 是什么。它处理不同的抽象。它有一个内置的实体缓存,并且知道这些实体处于什么状态。但是,UnitOfWork 可以注入到存储库中。

正确实现 UnitOfWork、IdentityMap、变更跟踪、延迟加载是乏味的。您确实应该使用现有的 ORM 作为基础设施层,帮助您专注于重要的事情 - 领域。

UnitOfWork is an infrastructural pattern that is already implemented by ORM, just like Identity Map. You don't have to reinvent the wheel. Repository on the other hand is a part of your domain model. Repository and UnitOfWork operate at different levels. UnitOfWork does not need to call Repository because it does not know what Repository is. It deals with different abstractions. It has a built-in cache of entities and it knows what state these entities are in. UnitOfWork however can be injected into Repository.

Proper implementation of UnitOfWork, IdentityMap, Change Tracking, Lazy loading is tedious. You should really be using existing ORM as an infrastructure layer that helps you keeping focus on what is important - domain.

如果没结果 2024-12-13 04:46:13

解决此问题的最常见方法之一是使用控制反转。

例如,您拥有 User 和 Comment 类,并且实现了通用存储库 IRepository。获取 User 或 Comment 的存储库只需提供 TDomainObject 参数:

  • IRepository
  • IRepository

稍后,您已经配置了谁来实现 IRepository;IRepository,所以如果您使用 Microsoft Pattern & 之类的东西, Practices 的公共服务定位器,我们位于您的工作单元中的 commit 方法主体中:

foreach(DomainObject some in NewObjects)
{
        ((IRepository<DomainObject>)ServiceLocator.Current.GetInstance(Type.GetType(string.Format("NamespacesToGenericRepository.IRepository`1[[{0}]]", some.GetType().FullName)))).Add(some); 
}

注意 IRepository 有一个逆变 TDomainObject 通用参数,该类型必须继承名为 DomainObject 的域对象的基本类型,它允许向上转换类似的内容IRepositoryIRepository

换句话说,您的 IRepository 接口签名将如下所示:

public interface IRepository<out TDomainObject>
    where TDomainObject : DomainObject

这只是关于如何实现定位具体存储库的摘要和/或提示,因此是一个工作单元 域对象可以管理任何专用域对象。

如果您想了解有关控制反转的更多信息,请查看这篇维基百科文章:

而且,根据我自己的经验,我想建议您将温莎城堡作为控制反转框架的选择:

One of most common ways of solving this is using inversion of control.

For example, you've your classes User and Comment, and you've implemented a generic repository IRepository<TDomainObject>. That's getting a repository of User or Comment is just giving the TDomainObject parameter:

  • IRepository<User>
  • IRepository<Comment>

Later you've configured who's implementing IRepository<User> and IRepository<Comment>, so if you use something like Microsoft Pattern & Practices' Common Service Locator, and we're in the body of commit method in your unit of work:

foreach(DomainObject some in NewObjects)
{
        ((IRepository<DomainObject>)ServiceLocator.Current.GetInstance(Type.GetType(string.Format("NamespacesToGenericRepository.IRepository`1[[{0}]]", some.GetType().FullName)))).Add(some); 
}

Note IRepository<TDomainObject> has a contravariant TDomainObject generic parameter which type must inherit a base type of Domain Object called DomainObject, which permits an upcast of something like IRepository<User> to IRepository<DomainObject>.

In other words, your IRepository<TDomainObject> interface signature will look like this:

public interface IRepository<out TDomainObject>
    where TDomainObject : DomainObject

This is just a summary and/or hint about how to implement locating the concrete repository so an unit of work of domain objects can manage ones of any specialized domain object.

If you want to learn more about inversion of control check this Wikipedia article:

And, because of my own experience, I'd like to suggest you Castle Windsor as inversion of control framework of choice:

醉城メ夜风 2024-12-13 04:46:13

这通常通过更改跟踪来实现,无论工作单元/会话/上下文在实体上发生什么操作,工作/会话/上下文都会意识到并在提交时执行适当的操作。

更改状态可以包括新建、修改和删除。

检查此链接了解更多信息。

使用它的实现可能有助于获得更好的想法。

实体框架实现了工作单元模式。也许使用它会让你更好地理解它。

This is typically implemented via change tracking , whatever action that happens on an entity the Unit of work/session/context is aware and performs the appropriate action on commit.

Change states could include New, Modified and Deleted.

check this link for more info.

It might help to use an implementation of it to get a better idea.

The entity framework implements the unit of work pattern. Maybe using it will let you understand it better.

情场扛把子 2024-12-13 04:46:13

您有多种方法:

  1. 更改跟踪,通过创建一个将更改存储在内存中直到您要求提交的 UnitOfWork 类,实现可以是:RegisterAdd(entity)、RegisterDelete(entity)、RegisterUpdate(entity),...然后提交();它将迭代所有已注册的更改并提交。 (http://msdn.microsoft.com/en-us/magazine/dd882510 .aspx
  2. 您可以使用 TransactionScope 作为分布式事务来对所有更新进行分组并在工作单元结束时提交。 (如何实现工作单元仅使用 TransactionScope 和 sqlconnections

You have multiple approaches:

  1. Change tracking, by creating a UnitOfWork class that stores changes in memory till you ask to commit, an implementation could be: RegisterAdd(entity), RegisterDelete(entity), RegisterUpdate(entity), .... then Commit(); which will iterate through all registered changes and commit. (http://msdn.microsoft.com/en-us/magazine/dd882510.aspx)
  2. You can use TransactionScope as a distributed transaction to group all updates and commit at the end of unit of work. (how to implement Unit Of Work just using just TransactionScope and sqlconnections)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文