将工作单元
和存储库模式
组合在一起是当今使用相当广泛的东西。正如Martin Fowler所说,使用UoW
的目的是在不了解存储库实际工作方式的情况下形成业务事务(持续无知)。我已经审查了许多实现;并且忽略特定细节(具体/抽象类、接口等),它们或多或少类似于以下内容:
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
的共享实例,所以每个Repostory
都可以访问UoW上的方法Commit
。由一个存储库调用它会使所有其他存储库也存储它们的更改;因此,整个事务概念崩溃了:
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
。
PS:我知道我可以告诉我的开发人员不要在存储库
中调用 Commit
,但受信任的架构比受信任的开发人员更可靠!
不要传入UnitOfWork
,传入一个具有您需要的方法的接口。如果需要,您仍然可以在原始的具体UnitOfWork
实现中实现该接口:
public interface IDbContext
{
void Add<T>(T entity);
}
public interface IUnitOfWork
{
void Commit();
}
public class UnitOfWork : IDbContext, IUnitOfWork
{
public void Add<T>(T entity);
public void Commit();
}
public class RepositoryBase<T>
{
private IDbContext _c;
public RepositoryBase(IDbContext c)
{
_c = c;
}
public void Add(T entity)
{
_c.Add(entity)
}
}
编辑
发布这个之后,我重新思考了一下。在UnitOfWork
实现中公开Add方法意味着它是两种模式的组合。
我在自己的代码中使用实体框架,这里使用的< code>DbContext被描述为“工作单元和存储库模式的组合”。
我认为最好将两者分开,这意味着我需要两个关于< code>DbContext的包装器,一个用于工作单元位,一个用于存储库位。我在< code>RepositoryBase中进行存储库包装。
关键区别在于,我没有将< code>UnitOfWork传递给存储库,而是传递了< code>DbContext。这意味着< code>BaseRepository可以访问< code>DbContext上的< code>SaveChanges。因为目的是自定义存储库应该继承< code>BaseRepository,所以它们也可以访问< code>DbContext。因此,开发人员可以在使用< code>DbContext的自定义存储库中添加代码。所以我想我的“包装”有点漏...
那么是否值得为 DbContext
创建另一个可以传递给存储库构造函数以关闭它的包装器?不确定是不是...
传递 DbContext 的示例:
实现存储库和工作单元
实体框架中的存储库和工作单元
约翰·帕帕的原始源代码
使您的仓库成为您的 UoW 的成员。不要让您的仓库“看到”您的 UoW。让 UoW 处理交易。
我同意你的担心。我更喜欢有一个环境工作单元,其中打开工作单元的最外层函数是决定提交还是中止的函数。被调用的函数可以打开一个工作范围单元,如果有工作范围单元,它会自动在环境UoW中登记,如果没有工作范围单元,则创建一个新的工作范围单元。
我使用的< code>UnitOfWorkScope的实现在很大程度上受到了< code>TransactionScope工作方式的启发。使用环境/范围方法还消除了依赖注入的需要。
执行查询的方法如下所示:
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();
}
请注意,呜。SaveChanges
() 调用只会在根(最远)范围的情况下对数据库进行实际保存。否则,将解释为允许根范围保存更改的“好投票”。
UnitOfWorkScope
的整个实现可在以下位置获得:http://coding.abel.nu/2012/10/make-the-dbcontext-ambient-with-unitofworkscope/
问题内容: 关于Spring JPA存储库事务性的1个快速问题。我有未标记为事务性的服务,并调用了Spring JPA存储库方法 它被定义为 问题是它失败,并且“ 没有EntityManager,当前线程没有可用的实际事务- 无法可靠地处理’remove’调用;嵌套异常是javax.persistence.TransactionRequiredException “异常。 好的,我可以通过将服务
关于Spring JPA存储库事务性的1个快速问题。我有一个未标记为事务性的服务,并调用Spring JPA存储库方法 好的,我可以通过标记服务或deleteByEmail(..)来解决它方法作为事务性的,但我就是不明白为什么它现在会崩溃。Spring文档明确指出“存储库实例上的CRUD方法在默认情况下是事务性的。”(http://docs.spring.io/spring-data/jpa/do
本文向大家介绍事务存储器,包括了事务存储器的使用技巧和注意事项,需要的朋友参考一下 事务性内存起源于数据库理论,它为进程同步提供了另一种策略。 内存事务是原子的,是一系列内存读写操作。如果事务中的所有操作都已完成,则将提交内存事务。否则,必须中止操作并回滚。可以通过添加到编程语言中的功能来获得事务存储的便利性。考虑一个例子。假设我们有一个修改共享数据的函数。传统上,此功能将使用互斥锁(或信号量)编
我有一个用例,我需要从一个Kafka主题中消费,做一些工作,生成另一个只有一次语义的Kafka主题,并保存到mongo数据库。看完文档后,我想kafka事务和mongo事务可以同步,但它们仍然是两个不同的事务。在下面的场景中,如果mongo提交失败,是否有方法回滚提交到主题并从消费者处重播的kafka记录。
本文向大家介绍MSSQL事务的存储过程,包括了MSSQL事务的存储过程的使用技巧和注意事项,需要的朋友参考一下 在酒店管理系统开发中,我们会创建房间表和房间类型表(房型表)这两个表,如下图所示: 房型表:RoomType 房间表:Room 首先这两个表的关系:Room是从表,RoomType是主表,两表有主外键关系,RoomType.rTypeId=Room.rType
主要内容:实现,步骤 1,BusinessService.java,步骤 2,EJBService.java,JMSService.java,步骤 3,BusinessLookUp.java,步骤 4,BusinessDelegate.java,步骤 5,Client.java,步骤 6,BusinessDelegatePatternDemo.java,步骤 7业务代表模式(Business Delegate Pattern)用于对表示层和业务层解耦。它基本上是用来减少通信或对表示层代码中的业务