1

私が取り組んでいるプロジェクトには、セッション全体に対して定義された 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 セッションを使用します

4

1 に答える 1

3

あなたの MVC Web サイトは、必要な操作を非常に簡単にする依存性注入コンテナーとして StructureMap を使用しているようです。

いくつかのオプションがありますが、最も簡単な方法は、StructureMap から ISession の新しいインスタンスを要求することです。これにより、UnitOfWork で使用されているものとは異なる新しい ISession が返されます。

次に例を示します。

var session = StructureMap.ObjectFactory.GetInstance<ISession>();

using ( var tx = session.BeginTransaction() )
{
    try
    {
        // Do your work here

        tx.Commit();
    }
    catch ( Exception )
    {
        tx.Rollback();

        throw;
    }
}

DI コンテナーを使用しているため、StructureMap の依存性注入を利用して、コントローラー/クラス/リポジトリなどのコンストラクターに新しい ISession を注入することもできます。そのため、StructureMap の ObjectFactory.GetInstance<>( ) 方法。

于 2012-08-24T00:30:27.800 に答える