我有一个像这样的存储库:
public interface IRepository
{
void Save<T>(T entity);
void Create<T>(T entity);
void Update<T>(T entity);
void Delete<T>(T entity);
IQueryable<T> GetAll<T>();
}
我的问题是,我的交易边界应该在哪里?我应该在每个方法上打开一个新事务并在返回之前提交它吗?或者它应该在整个存储库周围,以便只在存储库被处理/垃圾收集时提交事务?
答案 0 :(得分:3)
交易不应该应用于存储库,因为如果多个人需要参与交易,就无法说出来。
有一个单独的服务层,它使用存储库和模型对象来满足用例。服务方法知道事务边界需要在哪里。这就是他们应该应用的地方。
答案 1 :(得分:1)
工作单位绝对是最佳选择。如果您将SQL Server与本地数据库一起使用,TransactionScope
将为您完成大部分繁重工作;只要你在存储库之间共享会话(你通过构造函数注入,正确......?),那么你可以将它们嵌入到你内心的内容中。默认情况下,如果有“环境”事务,它会在“环境”事务中登记,如果没有,则启动新事务,这正是您对工作单元所需的行为。
因此,您的存储库可能如下所示:
public class UserRepository : IUserRepository
{
public UserRepository(ISession session)
{
this.Session = session;
}
public void Save(User user)
{
using (TransactionScope tsc = new TransactionScope())
{
Session.Save(user);
tsc.Complete();
}
}
protected ISession Session { get; set; }
}
public class OrderRepository : IOrderRepository
{
public OrderRepository(ISession session)
{
this.Session = session;
}
public void Save(Order order)
{
using (TransactionScope tsc = new TransactionScope())
{
Session.Save(order);
tsc.Complete();
}
}
protected ISession Session { get; set; }
}
然后你可以像这样执行完整的工作单元:
User currentUser = GetCurrentUser();
using (TransactionScope tsc = new TransactionScope())
{
ISession session = SessionFactory.OpenSession();
Order order = new Order(...);
order.User = currentUser;
IOrderRepository orderRepository = GetOrderRepository(session);
orderRepository.Save(order);
currentUser.LastOrderDate = DateTime.Now;
IUserRepository userRepository = GetUserRepository(session);
userRepository.Save(currentUser);
tsc.Complete();
}
如果你不喜欢TransactionScope
或者你的环境阻止你有效地使用它,那么你总是可以实现自己的UOW或使用现有的实现。或者,如果你只是一个建筑整洁的怪物,那么你可以做两件事 - 使用一个主要DI库的通用工作单元接口,并使用TransactionScope
实现你的具体UOW。
答案 2 :(得分:0)
其中一个选项是工作单元模式。以前的几个问题已经对此进行了解释。