私が取り組んでいるプロジェクトには、セッション全体に対して定義された UnitOfWork があります (MVC + NHibernate サイトの標準的な方法のようです)。
私がしなければならないことは、アイテムのコレクションをループして、独自の「ローカル」トランザクションで 1 つずつ処理できるようにすることです。
このようなもの:
foreach(var item in CollectionOfItems)
{
using (ITransaction transaction = UnitOfWork.CurrentSession.BeginTransaction())
{
//do work on item. rollback on failure,
//but it should not affect the other items
}
}
しかし、BeginTransaction 行が同じ「外部」セッションを使用しているため、これは機能しません。コードの小さなブロックでトランザクションを実行する自己完結型の「ローカル」セッションを取得するにはどうすればよいですか? 次のコードでは、作業単位にセッションが挿入されていると思います。ただし、正確な方法はわかりません。
UnitOfWOrk クラスには、次のコンストラクターがあります。
private readonly ISessionFactory _sessionFactory;
private readonly ITransaction _transaction;
public UnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
CurrentSession = _sessionFactory.OpenSession();
_transaction = CurrentSession.BeginTransaction();
}
次の方法で登録されます。
For<IUnitOfWork>().LifecycleIs(new HybridLifecycle())
.Use<UnitOfWork>();
そのため、コントローラーが応答を返すたびに、セッションがフラッシュされます。これは私が混乱しているところです。私は常にすべてがすべてかゼロかを望んでいるわけではありません。
編集:
NHibernate 登録プロセスのすべてのコードは次のとおりです。
public NHibernateRegistry()
{
FluentConfiguration fluentConfig = Fluently.Configure()
.Database(
MsSqlConfiguration.MsSql2008.ShowSql().ConnectionString(x => x.FromConnectionStringWithKey("conn")))
.ProxyFactoryFactory(typeof (ProxyFactoryFactory).AssemblyQualifiedName)
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<CustomerMap>());
Configuration configuration = fluentConfig.BuildConfiguration();
ConfigureNhibernateValidator(configuration);
ISessionFactory sessionFactory = fluentConfig.BuildSessionFactory();
For<Configuration>().LifecycleIs(new HybridLifecycle()).Singleton().Use(configuration);
For<ISessionFactory>().LifecycleIs(new HybridLifecycle()).Singleton().Use(sessionFactory);
For<ISession>().LifecycleIs(new HybridLifecycle())
.Use(x => x.GetInstance<ISessionFactory>().OpenSession());
For<IUnitOfWork>().LifecycleIs(new HybridLifecycle())
.Use<UnitOfWork>();
For<ITssPrincipal>().HybridHttpOrThreadLocalScoped().Use(container => BuildUserInstanceFromThreadCurrentPrincipal());
Scan(x =>
{
x.TheCallingAssembly();
x.WithDefaultConventions();
});
}
編集: DI 問題の例 以下の例では、RepoA が RepoB で DI され、両方とも StructureMap によって提供される UnitOfWork を取得することがわかります。
public RepoA(IUnitOfWork unitOfWork, ITssPrincipal principal,
IRepoB repoB)
{
}
public RepoB(IUnitOfWork unitOfWork, ITssPrincipal principal)
{
}
RepoA の関数で新しいセッションを作成しても、repoB は引き続き元の UnitOfWork セッションを使用します