我正在尝试将域模型编写为尽可能持久性无知。我现在唯一要做的就是标记每个属性和方法virtual
,因为NHibernate要求延迟加载。
在我的域模型程序集中,我定义了一些存储库接口:
public interface IRepository<TEntity> where TEntity : EntityBase {
TEntity Get(int id);
/* ... */
}
public interface IProductRepository : IRepository<Product> { ... }
然后我有数据汇编。这个将引用NHibernate,它知道它的存在。这是实现这些存储库接口的程序集:
public abstract class Repository<TEntity> : IRepository<TEntity> {
public TEntity Get(ind id) { ... }
/* ... */
}
public class ProductRepository : Repository<Product>, IProductRepository {
/* ... */
}
等等。
现在我想实现交易功能到我的存储库。为此,我将在我的IRepository接口上添加BeginTransaction
方法。但是,我无法将其返回类型定义为NHibernate.ITransaction
,因为我想保持域模型持久性无知,而不是被迫从我的域模型程序集引用NHibernate的程序集。
你会做什么?
您是否只需在界面上实施void BeginTransaction()
,void Commit()
和void RollBack()
方法,然后让存储库实施在内部管理ITransaction
对象
或者你会找到一种方法公开ITransaction
对象让客户端直接使用它来管理事务,而不是使用存储库的方法吗?
谢谢!
答案 0 :(得分:2)
您可以查看已经实现了所有内容的Sharp Architecture,包括具有事务支持的通用存储库。解决方案是IRepository具有封装事务的DbContext属性(它实际上是一个接口)。 这是您描述的第一个选项(隐藏NHibernate的自定义事务接口)。它运作良好。
我想你甚至可以重复使用S#arp代码,无论你是否打算使用完整的框架。
答案 1 :(得分:0)
IMO事务总是应该以业务逻辑开始和结束,换句话说,事务应该从服务层而不是存储库层开始,并且存储库应该在事务中登记它自己,理想情况下这将是隐式完成的。
现在如果您正在使用NH,那么如果您的服务和存储库共享相同的“会话”(他们应该),那么您可以在服务层中调用“BeginTransaction”并根据需要提交或回滚:
例如,想象一下服务上的这个方法:
public void RegisterCustomer(Customer customer) { try { using(var transaction = _session.BeginTransaction()) { _customerRepository.Save(customer); _customerSurveyRepository.Save(customerSurvey); // DO What ever else you want... transaction.Commit(); } } catch (Exception exn) { throw new AMException(FAILED_REGISTRATION, exn); } }
如何通过注入构造函数或使用SessionFactory获取当前会话来解决存储库如何获取对同一Session的引用...