C#使用IRepository的共享交易和NHibernate
我正在研究使用NHibernate实现IRepository模式,我有一个问题,我无法回答搜索网络的问题 假设我有3个存储库,PersonRepository、PersonalAddressRepository和PersonalCountRepository。现在假设业务逻辑规定有一个“Deactivate Person”流程,该流程调用PersonRepository.Deactivate()、PersonAddressRepository.Deactivate()和PersonacconRepository.Deactivate() 我希望能够按照……的思路做些事情C#使用IRepository的共享交易和NHibernate,c#,nhibernate,transactions,irepository,C#,Nhibernate,Transactions,Irepository,我正在研究使用NHibernate实现IRepository模式,我有一个问题,我无法回答搜索网络的问题 假设我有3个存储库,PersonRepository、PersonalAddressRepository和PersonalCountRepository。现在假设业务逻辑规定有一个“Deactivate Person”流程,该流程调用PersonRepository.Deactivate()、PersonAddressRepository.Deactivate()和PersonacconRe
using (ITransaction transaction = session.BeginTransaction()) {
session.Update(Person);
session.Update(PersonAddress);
session.Update(PersonAccount);
}
因此,如果这些更新中的任何一个失败,整个过程将回滚到数据库中。现在我对NHibernate的理解是,你只能为每个对象创建一个会话,所以
var cfg = new Configuration();
cfg.Configure();
cfg.AddAssembly(typeof(Person).Assembly);
ISessionFactory sessionFactory = cfg.BuildSessionFactory();
using (ISession session = sessionFactory.OpenSession()) {
using (ITransaction transaction = session.BeginTransaction()) {
session.Save(Person);
}
这是正确的还是我弄错了?关于多表更新的事务和关于NHibernate的事务的最佳实践是什么
提前感谢。您不应该在存储库或“下面”的其他地方创建事务。事务由应用程序逻辑定义。这是我在事务处理中看到的最常见的错误之一 我编写了一个事务服务来管理事务:
using (TransactionService.CreateTransactionScope())
{
repositoryA.DoX();
repositoryB.DoY();
TransactionService.Commit();
}
存储库正在从服务获取具有打开事务的会话:
TransactionService.Session.CreateQuery("...");
根据您的环境,您需要将其变得更加复杂。例如,会话可能对业务逻辑不可见,应该放在另一个接口上等。您不应该在存储库或其他“下面”的地方创建事务。事务由应用程序逻辑定义。这是我在事务处理中看到的最常见的错误之一 我编写了一个事务服务来管理事务:
using (TransactionService.CreateTransactionScope())
{
repositoryA.DoX();
repositoryB.DoY();
TransactionService.Commit();
}
存储库正在从服务获取具有打开事务的会话:
TransactionService.Session.CreateQuery("...");
根据您的环境,您需要将其变得更加复杂。例如,会话可能对业务逻辑不可见,应该放在另一个接口上等等。我认为NHibernate理解System.Transactions.TransactionScope类。为什么不使用它?我以为NHibernate理解System.Transactions.TransactionScope类。您为什么不使用它呢?您可以做的一件事——我现在就是这样做的——就是将应用于存储库实例的ISession实例传递给存储库实例 我将来要做的是:
- 我有一个
类,它非常通用,是NHibernate的UnitOfWork
对象的包装器。此UnitOfWork类不包含“应用程序”或特定于域的方法ISession
- 在使用NHibernate(和我的UnitOfWork包装器)的项目中,我将在
类上创建一组扩展方法,如下所示:UnitOfWork
public static class UnitOfWorkExtension` { public static IPersonRepository GetPersonRepository( this UnitOfWork uow) { return new PersonRepository(uow); } public static IAccountRepository GetAccountRepository( this UnitofWork uow ) { return new AccountRepository(uow); } }
using( var uow = unitOfWorkFactory.CreateUnitOfWork() )
{
var person = uow.GetPersonRepository().GetPerson (1);
var accounts = uow.GetAccountRepository().GetAccountsForPerson(person);
}
但是,看看你的例子,我想知道你是否应该有一个“PersonalAddress”和“PersonalAccount”的存储库。
依我拙见,
Person
是一个“聚合根”,在您的示例中,它由PersonAddress
和PersonAccount
组成,并且应该有一个PersonRepository
来处理Person聚合根(包括PersonalAddress和PersonalAccount对象——事实上,它们不是实体,而是值对象(在我看来))。您可以做的一件事——我现在就是这样做的——就是将应用于存储库实例的ISession实例传递给您的存储库实例
我将来要做的是:
- 我有一个
类,它非常通用,是NHibernate的UnitOfWork
对象的包装器。这个UnitOfWork类不包含“应用程序”或特定于域的方法ISession
- 在使用NHibernate(和我的UnitOfWork包装器)的项目中,我将在
类上创建一组扩展方法,如下所示:UnitOfWork
public static class UnitOfWorkExtension` { public static IPersonRepository GetPersonRepository( this UnitOfWork uow) { return new PersonRepository(uow); } public static IAccountRepository GetAccountRepository( this UnitofWork uow ) { return new AccountRepository(uow); } }
using( var uow = unitOfWorkFactory.CreateUnitOfWork() )
{
var person = uow.GetPersonRepository().GetPerson (1);
var accounts = uow.GetAccountRepository().GetAccountsForPerson(person);
}
但是,看看你的例子,我想知道你是否应该有一个“PersonalAddress”和“PersonalAccount”的存储库。
依我拙见,
Person
是一个“聚合根”,在您的示例中,它由PersonAddress
和PersonAccount
组成,并且应该有一个PersonRepository
来处理Person聚合根(包括PersonalAddress和PersonalAccount对象——实际上它们不是实体,而是值对象(在我看来)).您好,谢谢您的回答,我的后续问题是,此TransactionService是否有效地管理了一个事务池,以便在一个事务池失败时,池中的所有事务都将回滚?或者是否有一种方法可以跨多个存储库共享一个事务?每个线程有一个事务。当然,其他并行事务c在其他线程上。你好,谢谢你的回答,我的后续问题是,这个事务服务实际上是管理一个事务池,这样如果一个失败,那么池中的所有事务都被回滚了?或者有一种方法可以在多个存储库中共享1个事务吗?每个线程都有一个事务。当然,其他的PAR。所有事务在其他线程上进行。