Как избежать, чтобы сеанс ASP.NET SqlServer мешал окружающему Transaction-Per-Request? - PullRequest
1 голос
/ 20 мая 2010

Я пытаюсь использовать область транзакции в шаблоне транзакции на запрос. Итак, у меня есть модуль http, который делает (упрощенно):

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"/>

Теперь, при случайной оценке, примерно одна страница из десяти дает мне следующую ошибку:

[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 один?

    Заранее спасибо,

    Julien

Ответы [ 2 ]

2 голосов
/ 26 сентября 2012

Это некро-ответ, но ответ на вопрос в случае, если кто-то еще случайно сталкивается с этим, в то время как Google прибавляет в сумме Enlist=False к SqlServerSessionState connection string.

Из-за нечетного времени соединение, используемое для получения сеанса, может иногда включаться в транзакцию окружения, даже если вы, вероятно, предпочли бы, чтобы оно не было.

Установка Enlist=False в строке соединения гарантирует, что ваши соединения состояния сеанса не будут обрабатывать внешнюю транзакцию и, таким образом, приведут к хорошей быстрой транзакции, которая будет преобразована в более медленную распределенную транзакцию.

0 голосов
/ 20 мая 2010

Я не совсем уверен в том, как работает ваш код, но вы можете подавить внешнюю транзакцию следующим образом, что может помочь:

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...