2013-07-18 3 views
5

Я использую EF5.0 с SQL Server 2008. У меня есть две базы данных на одном экземпляре сервера. Мне нужно обновить таблицы в обеих базах данных и сделать их одной транзакцией. Поэтому я использовал TransactionScope. Ниже приведен код -Несколько баз данных (datacontext) на одном сервере без MS DTC

public void Save() 
{ 
     var MSObjectContext = ((IObjectContextAdapter)MSDataContext).ObjectContext; 
     var AWObjectContext = ((IObjectContextAdapter)AwContext).ObjectContext; 

     using (var scope = new TransactionScope(TransactionScopeOption.Required, 
              new TransactionOptions 
               { 
                IsolationLevel = IsolationLevel.ReadUncommitted 
               })) 
     {    
      MSObjectContext.SaveChanges(SaveOptions.DetectChangesBeforeSave); 
      AWObjectContext.SaveChanges(SaveOptions.DetectChangesBeforeSave); 

      scope.Complete(); 
     } 
    } 

При использовании вышеуказанного кода Transaction присваивается код DTC. После поиска в Интернете я обнаружил, что это происходит из-за двух разных подключений/соединений. Но я не понимаю, что если я напишу хранимую процедуру в одной базе данных, которая обновляет таблицу в другой базе данных (на том же сервере), DTC не требуется. Тогда почему EF или TransactionScope продвигают это в DTC? Есть ли другая работа для этого?

Пожалуйста посоветуйте

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

Саи

ответ

4

С равнинных DbConnection с, вы можете предотвратить DTC эскалации нескольких баз данных на одном сервере, используя ту же строку подключения (с любой базой данных, например) и вручную изменить базу данных на открытом объекте соединения следующим образом:

using (var tx = new TransactionScope()) 
{ 
    using (var conn = new SqlConnection(connectStr)) 
    { 
     conn.Open(); 
     new SqlCommand("INSERT INTO atest VALUES (1)", conn).ExecuteNonQuery(); 
    } 
    using (var conn = new SqlConnection(connectStr)) 
    { 
     conn.Open(); 
     conn.ChangeDatabase("OtherDB"); 
     new SqlCommand("INSERT INTO btest VALUES (2)", conn).ExecuteNonQuery(); 
    } 
    tx.Complete(); 
} 

Это не будет переходить на DTC, но это было бы, если бы вы использовали разные значения для connectStr.

Я не знаком с EF и как он управляет соединениями и контекстами, но используя приведенную выше информацию, вы можете избежать эскалации DTC, выполнив conn.ChangeDatabase(..), а затем создав свой контекст, например new DbContext(conn, ...).

Но обратите внимание, что даже с общей строкой подключения, как только у вас есть два открытых соединений в то же время, DTC будет участвовать, как в этом примере модификации:

using (var tx = new TransactionScope()) 
{ 
    using (var conn = new SqlConnection(mssqldb)) 
    { 
     conn.Open(); 
     new SqlCommand("INSERT INTO atest VALUES (1)", conn).ExecuteNonQuery(); 
     using (var conn2 = new SqlConnection(mssqldb)) 
     { 
      conn2.Open(); 
      conn2.ChangeDatabase("otherdatabase"); 
      new SqlCommand("INSERT INTO btest VALUES (2)", conn2).ExecuteNonQuery(); 
     } 
    } 
    tx.Complete(); 
} 
+0

Я хочу совершить транзакции на двух совершенно разных dbs на одном сервере в рамках одной транзакции. Я мог бы это сделать с помощью хранимых процедур, но не через EF. Спасибо за ваш ответ. – Sai

+0

Мой ответ показывает, как использовать TransactionScope для этого, не прибегая к сохраненным процессам. Неявная 'tx.Dispose()', которая возникает после строки 'tx.Complete()', будет фиксировать единственную транзакцию, которая включает оба INSERT в две разные базы данных. Как уже упоминалось, с EF существуют способы предоставления соединений, в которых вы вручную называете 'ChangeDatabase()', но в зависимости от вашей базы кода, это может привести к более высокосвязанному коду (в то время как точка «TransactionScoep» - это развязка кода) только вы можете сказать. –

+0

Я не думаю, что могу использовать ChangeDatabase(), поскольку я использую метод Databasefirst, а мой dbcontext тесно связан с сущностями. Если я изменил строку соединения во время выполнения на совершенно другую базу данных, это вызовет ошибку. – Sai

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