簡體   English   中英

UnitOfWork Sessions中的NHibernate事務

[英]NHibernate transactions within UnitOfWork Sessions

我正在開發的項目有一個為整個會話定義的UnitOfWork(似乎是MVC + NHibernate站點的標准做法)

但是我需要做的是,能夠遍歷一組項目並在他們自己的“本地”事務中逐個訪問它們。

這樣的事情:

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'd並且都獲得StructureMap提供的UnitOfWork。

public RepoA(IUnitOfWork unitOfWork, ITssPrincipal principal,
     IRepoB repoB)
{
}

public RepoB(IUnitOfWork unitOfWork, ITssPrincipal principal)
{
}

即使我在RepoA中的函數中創建新會話,repoB仍將使用原始的UnitOfWork會話

看起來你的MVC網站正在使用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 <>( ) 方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM