2010-05-20 1 views
1

Я пытаюсь использовать область транзакции в шаблоне транзакции за запрос. Таким образом, у меня есть модуль HTTP, которые (упрощенный):Как избежать сеанса ASP.NET SqlServer для вмешательства в окружающий транзакционный запрос?

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 

То, что я (думаю, I) понять, что подключение к базе данных сеанса ASP.NET иногда зачислен в моей бизнес-операции, и я получаю эту ошибку, когда мой бизнес-операции я сначала заканчивается.

Существует несколько проблем с этим:

  • Я не думаю, что сделка для состояния сеанса должна быть такой же, как мой бизнес один. Это две отдельные проблемы.
  • Он автоматически переводит транзакцию в распределенный (MSDTC), что влияет на мою производительность.

    Как отделить бизнес-транзакцию от сеанса ASP.NET?

    Спасибо заранее,

    Julien

ответ

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

Спасибо за ваш ответ, Балаз. Возможно, я не знаю. Мне нужна деловая сделка, поэтому я не хочу ее подавлять. Просто мне нужно, чтобы он отличался от сеанса ASP.NET. – Julien

+0

Это будет только подавлено в рамках этого внутреннего блока использования. Итак, выполняйте любую работу, связанную с сеансом, которую вы должны делать в этом блоке. Работа, связанная с сеансом, по-прежнему будет охватываться транзакцией (scope2). Однако отказ во внутренней транзакции не повлияет на внешнюю транзакцию. Это вариант «Подавить». Это просто заставляет содержащую область транзакции игнорировать этот блок кода. Я все еще не понимаю ваш вопрос? – balazs

2

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

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^