2010-11-19 50 views
1

NHibernate在參與分佈式事務時拋出異常,並且通過指定自己的連接對象來打開會話。NHibernate - 分佈式事務和提供自己的連接導致異常

Unhandled Exception: System.InvalidOperationException: Disconnect cannot be call 
ed while a transaction is in progress. 
    at NHibernate.AdoNet.ConnectionManager.Disconnect() 
    at NHibernate.Impl.SessionImpl.Close() 
    at NHibernate.Impl.SessionImpl.Dispose(Boolean isDisposing) 
    at NHibernate.Transaction.AdoNetWithDistrubtedTransactionFactory.<>c__Display 
Class1.<EnlistInDistributedTransactionIfNeeded>b__0(Object sender, TransactionEv 
entArgs e) 
    at System.Transactions.TransactionCompletedEventHandler.Invoke(Object sender, 
TransactionEventArgs e) 
    at System.Transactions.TransactionStatePromotedCommitted.EnterState(InternalT 
ransaction tx) 
    at System.Transactions.InternalTransaction.DistributedTransactionOutcome(Inte 
rnalTransaction tx, TransactionStatus status) 
    at System.Transactions.Oletx.RealOletxTransaction.FireOutcome(TransactionStat 
us statusArg) 
    at System.Transactions.Oletx.OutcomeEnlistment.InvokeOutcomeFunction(Transact 
ionStatus status) 
    at System.Transactions.Oletx.OletxTransactionManager.ShimNotificationCallback 
(Object state, Boolean timeout) 
    at System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback 
(Object state, Boolean timedOut) 

以下代碼將重現該問題;參考當前的FluentNibernate和NHibernate 2.1.2.4000。

using System; 
using System.Data.SqlClient; 
using System.Transactions; 

using FluentNHibernate.Mapping; 
using FluentNHibernate.Cfg.Db; 
using FluentNHibernate.Cfg; 

namespace ConsoleApplication2 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     var cfg = 
     Fluently.Configure().Database(
      MsSqlConfiguration.MsSql2008.ConnectionString("Integrated Security=SSPI;Data Source=.;Initial Catalog=Test").DefaultSchema("dbo") 
     ).Mappings(x => x.FluentMappings.AddFromAssemblyOf<MyTableMap>()).BuildConfiguration(); 

     using (var sf = cfg.BuildSessionFactory()) 
     { 
     using (var ts = new TransactionScope().PromoteToDtc()) 
     { 
      using (var conn = new SqlConnection("Integrated Security=SSPI;Data Source=.;Initial Catalog=Test")) 
      { 
      conn.Open(); 

      using (var session = sf.OpenSession(conn)) 
      { 
       session.Save(new MyTable { String = "Hello!" }); 
      } 
      } 

      ts.Complete(); 
     } 

     Console.WriteLine("It saved!"); 
     Console.ReadLine(); 
     } 
    } 
    } 

    public class DummyEnlistmentNotification : IEnlistmentNotification 
    { 
    public static readonly Guid Id = new Guid("E2D35055-4187-4ff5-82A1-F1F161A008D0"); 

    public void Prepare(PreparingEnlistment preparingEnlistment) 
    { 
     preparingEnlistment.Prepared(); 
    } 

    public void Commit(Enlistment enlistment) 
    { 
     enlistment.Done(); 
    } 

    public void Rollback(Enlistment enlistment) 
    { 
     enlistment.Done(); 
    } 

    public void InDoubt(Enlistment enlistment) 
    { 
     enlistment.Done(); 
    } 
    } 

    public static class TSExetensions 
    { 
    public static TransactionScope PromoteToDtc(this TransactionScope scope) 
    { 
     Transaction.Current.EnlistDurable(DummyEnlistmentNotification.Id, new DummyEnlistmentNotification(), EnlistmentOptions.None); 
     return scope; 
    } 
    } 

    public class MyTable 
    { 
    public virtual int Id { get; private set; } 
    public virtual string String { get; set; } 
    } 

    public sealed class MyTableMap : ClassMap<MyTable> 
    { 
    public MyTableMap() 
    { 
     Id(x => x.Id).GeneratedBy.Native(); 
     Map(x => x.String).Not.Nullable(); 
    } 
    } 
} 
+1

堆棧和異常表明您有一個分佈式事務仍在進行中。您的交易如何創建/管理? – 2010-11-19 15:08:38

+0

我們沒有做任何事情,NServiceBus在調用我們的消息處理代碼之前和之後自動啓動並評論分佈式事務。 – Andy 2010-11-21 21:36:49

回答

1

這個問題的確與NHiberate有關。他們正在開發一個補丁。作爲參考,可以找到問題here

相關問題