2010-05-20 51 views
1

我正在嘗試在每個請求事務模式中使用事務作用域。所以,我有那些(簡體)一個HTTP模塊:如何避免ASP.NET SqlServer會話干擾周圍Transaction-Per-Request?

private void Application_BeginRequest(object sender, EventArgs e) 
{ 
    var scope = new TransactionScope(TransactionScopeOption.RequiresNew); 
    PutScopeInHttpContext(scope); 
} 

private void Application_EndRequest(object sender, EventArgs e) 
{ 
    var scope = GetScopeFromHttpContext(); 
    try 
    { 
     if (HttpContext.Current.Error == null) 
     { 
      scope.Complete(); 
     } 
    } 
    finally 
    { 
     scope.Dispose(); 
    } 
} 

然後,在我的web.config,我有:

<httpModules> 
    <clear/> 
    <add name="OutputCache" type="System.Web.Caching.OutputCacheModule"/> 
    <add name="Session" type="System.Web.SessionState.SessionStateModule"/> 
    <add name="Profile" type="System.Web.Profile.ProfileModule"/> 
    <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> 
    <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> 
    <add name="TransactionPerRequestWebModule" type="Acme.Web.TransactionPerRequestWebModule, Acme.Web"/> 
</httpModules> 
<sessionState mode="SQLServer" sqlConnectionString="Data Source=localhost\SQLEXPRESS;Integrated Security=SSPI;" cookieless="false" timeout="360"/> 

現在,在什麼似乎是隨機速度,大約1頁出十給了我以下錯誤:

[SqlException (0x80131904): Distributed transaction completed. Either enlist this session in a new transaction or the NULL transaction.] 
    System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +1951450 
    System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +4849003 
    System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) +194 
    System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +2394 
    System.Data.SqlClient.SqlDataReader.ConsumeMetaData() +33 
    System.Data.SqlClient.SqlDataReader.get_MetaData() +83 
    System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +297 
    System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +954 
    System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +162 
    System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +32 
    System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +141 
    System.Data.SqlClient.SqlCommand.ExecuteReader() +89 
    System.Web.SessionState.SqlSessionStateStore.DoGet(HttpContext context, String id, Boolean getExclusive, Boolean& locked, TimeSpan& lockAge, Object& lockId, SessionStateActions& actionFlags) +516 

[HttpException (0x80004005): Unable to connect to SQL Server session database.] 
    System.Web.SessionState.SqlSessionStateStore.ThrowSqlConnectionException(SqlConnection conn, Exception e) +229 
    System.Web.SessionState.SqlSessionStateStore.DoGet(HttpContext context, String id, Boolean getExclusive, Boolean& locked, TimeSpan& lockAge, Object& lockId, SessionStateActions& actionFlags) +649 
    System.Web.SessionState.SqlSessionStateStore.GetItemExclusive(HttpContext context, String id, Boolean& locked, TimeSpan& lockAge, Object& lockId, SessionStateActions& actionFlags) +48 
    System.Web.SessionState.SessionStateModule.GetSessionStateItem() +117 
    System.Web.SessionState.SessionStateModule.BeginAcquireState(Object source, EventArgs e, AsyncCallback cb, Object extraData) +487 
    System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +66 
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155 

我(想我)明白的是,到ASP.NET會話數據庫的連接,在我的生意交易徵有時,我得到這個錯誤時,我的商業交易一世首先完成。

有幾個問題與:

  • 我不認爲對會話狀態的事務應該是一樣的我的業務之一。這是兩個不同的問題。
  • 它使交易自動升級爲分佈式(MSDTC),這會影響我的表現。

    如何解耦我的業務事務與ASP.NET會話之一?

    由於提前,

    朱利安

回答

0

我不能完全確定你的代碼是如何工作的,但可以抑制環境事務是這樣,這可能有助於:

using(TransactionScope scope1 = new TransactionScope()) 
{ 
    try 
    { 
      //Start of non-transactional section 
      using(TransactionScope scope2 = new 
      TransactionScope(TransactionScopeOption.Suppress)) 
      { 
       //Do non-transactional work here 
      } 
      //Restores ambient transaction here 
    } 
    catch 
    {} 
    //Rest of scope1 
} 
+0

感謝您的回答,Balazs。我可能不清楚。我需要一個商業交易,所以我不想壓制它。只是我需要它與ASP.NET會話不同。 – Julien 2010-05-20 18:53:25

+0

它只能在內部使用塊的範圍內被抑制。因此,在該區塊內進行與會話相關的工作。與會話相關的工作仍將由交易覆蓋(範圍2)。但是,內部交易中的失敗不會影響外部交易。這就是「Suppress」選項。它只是導致包含事務作用域忽略該代碼塊。 我還沒理解你的問題? – balazs 2010-05-20 19:52:46

2

這是一個回答Necro的問題,但如果有人在Google上隨機發現這個問題的答案是將Enlist=False添加到SqlServerSessionState connection string

由於時間奇怪,用於檢索會話的連接有時可以在環境事務中登記,即使您可能更喜歡它不會。

在連接字符串上設置Enlist=False可確保您的會話狀態連接不會接收環境事務,從而導致快速事務處理被提升爲較慢的分佈式事務。