工作单元 + 存储库模式:业务交易概念的堕落 [英] Unit of Work + Repository Pattern: The Fall of the Business Transaction Concept
问题描述
结合工作单元
和存储库模式
是当今使用相当广泛的东西.正如 Martin Fowler 所说,使用 UoW
的目的是形成一个 <强>业务交易,同时不知道存储库的实际工作方式(持续无知).我已经审查了许多实现;并忽略具体细节(具体/抽象类、接口等),它们或多或少类似于以下内容:
Combining Unit of Work
and Repository Pattern
is something used fairly widely nowadays. As Martin Fowler says a purpose of using UoW
is to form a Business Transaction while being ignorant of how repositories actually work (being persistent ignorant). I've reviewed many implementations; and ignoring specific details (concrete/abstract class, interface,...) they are more or less similar to what follows:
public class RepositoryBase<T>
{
private UoW _uow;
public RepositoryBase(UoW uow) // injecting UoW instance via constructor
{
_uow = uow;
}
public void Add(T entity)
{
// Add logic here
}
// +other CRUD methods
}
public class UoW
{
// Holding one repository per domain entity
public RepositoryBase<Order> OrderRep { get; set; }
public RepositoryBase<Customer> CustomerRep { get; set; }
// +other repositories
public void Commit()
{
// Psedudo code:
For all the contained repositories do:
store repository changes.
}
}
现在我的问题:
UoW
公开公共方法 Commit
来存储更改.此外,因为每个存储库都有一个 UoW
的共享实例,每个 Repository
都可以访问 UoW 上的方法 Commit
.通过一个存储库调用它会使所有其他存储库也存储它们的更改;因此,整个交易概念崩溃的结果:
UoW
exposes public method Commit
to store the changes. Also, because each repository has a shared instance of UoW
, each Repository
can access method Commit
on UoW. Calling it by one repository makes all other repositories store their changes too; hence the result the whole concept of transaction collapses:
class Repository<T> : RepositoryBase<T>
{
private UoW _uow;
public void SomeMethod()
{
// some processing or data manipulations here
_uow.Commit(); // makes other repositories also save their changes
}
}
我认为这一定是不允许的.考虑到 UoW
(业务事务)的目的,方法 Commit
应该只公开给发起 业务事务 的人,例如 Business层.令我惊讶的是,我找不到任何解决此问题的文章.在所有这些中 Commit
可以被任何被注入的 repo 调用.
I think this must be not allowed. Considering the purpose of the UoW
(business transaction), the method Commit
should be exposed only to the one who started a Business Transaction for example Business Layer. What surprised me is that I couldn't find any article addressing this issue. In all of them Commit
can be called by any repo being injected.
PS:我知道我可以告诉我的开发人员不要在 Repository
中调用 Commit
但受信任的架构比受信任的开发人员更可靠!
PS: I know I can tell my developers not to call Commit
in a Repository
but a trusted Architecture is more reliable than trusted developers!
推荐答案
我同意您的担忧.我更喜欢有一个环境工作单元,其中打开工作单元的最外层函数是决定是提交还是中止的函数.调用的函数可以打开一个工作范围单元,如果有,它会自动加入环境 UoW,如果没有,则创建一个新的.
I do agree with your concerns. I prefer to have an ambient unit of work, where the outermost function opening a unit of work is the one that decides whether to commit or abort. Functions called can open a unit of work scope which automatically enlists in the ambient UoW if there is one, or creates a new one if there is none.
我使用的 UnitOfWorkScope
的实现深受 TransactionScope
工作方式的启发.使用环境/范围方法还消除了依赖注入的需要.
The implementation of the UnitOfWorkScope
that I used is heavily inspired by how TransactionScope
works. Using an ambient/scoped approach also removes the need for dependency injection.
执行查询的方法如下所示:
A method that performs a query looks like this:
public static Entities.Car GetCar(int id)
{
using (var uow = new UnitOfWorkScope<CarsContext>(UnitOfWorkScopePurpose.Reading))
{
return uow.DbContext.Cars.Single(c => c.CarId == id);
}
}
写入的方法如下所示:
using (var uow = new UnitOfWorkScope<CarsContext>(UnitOfWorkScopePurpose.Writing))
{
Car c = SharedQueries.GetCar(carId);
c.Color = "White";
uow.SaveChanges();
}
请注意,如果这是根(最远的)范围,uow.SaveChanges()
调用只会对数据库进行实际保存.否则,它被解释为同意投票",即允许根范围保存更改.
Note that the uow.SaveChanges()
call will only do an actual save to the database if this is the root (otermost) scope. Otherwise it is interpreted as an "okay vote" that the root scope will be allowed to save the changes.
UnitOfWorkScope
的整个实现可在以下位置获得:http://coding.abel.nu/2012/10/make-the-dbcontext-ambient-with-unitofworkscope/
The entire implementation of the UnitOfWorkScope
is available at: http://coding.abel.nu/2012/10/make-the-dbcontext-ambient-with-unitofworkscope/
这篇关于工作单元 + 存储库模式:业务交易概念的堕落的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!