2014-01-13 2 views
4

Итак, у меня есть две базы данных ... база данных Users и другая база данных, которая также содержит таблицу Users. У обоих есть поле электронной почты. Я хотел бы обновить оба поля электронной почты одновременно.Обеспечение целостности над 2 базами данных

The (упрощенно) код выглядит примерно так:

using(var db1 = new Db1Context()) 
using(var db2 = new Db2Context()) 
{ 
    db1.Users.Single(u => u.Email == oldEmail).Email = someEmail; 
    db2.Users.Single(u => u.Email == oldEmail).Email = someEmail; 
    db1.SaveChanges(); 
    db2.SaveChanges(); //what if this fails? 
} 

Таким образом, попытка 1:

using(var db1 = new Db1Context()) 
using(var db2 = new Db2Context()) 
using(var txs = new TransactionScope()) 
{ 
    db1.Users.Single(u => u.Email == oldEmail).Email = someEmail; 
    db2.Users.Single(u => u.Email == oldEmail).Email = someEmail; 
    db1.SaveChanges(); 
    db2.SaveChanges(); //what if this fails? 
    txs.Complete(); 
} 

завершается с ArgumentException и следующие StackTrace:

[ArgumentException: Value does not fall within the expected range.] 
    System.Transactions.Oletx.IDtcProxyShimFactory.ConnectToProxy(String nodeName, Guid resourceManagerIdentifier, IntPtr managedIdentifier, Boolean& nodeNameMatches, UInt32& whereaboutsSize, CoTaskMemHandle& whereaboutsBuffer, IResourceManagerShim& resourceManagerShim) +0 
    System.Transactions.Oletx.DtcTransactionManager.Initialize() +155 
    System.Transactions.Oletx.DtcTransactionManager.get_ProxyShimFactory() +76 
    System.Transactions.TransactionInterop.GetOletxTransactionFromTransmitterPropigationToken(Byte[] propagationToken) +160 
    System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction tx) +78 
...[etc...] 

Как мы понимаем вещи, это потому, что Azure does not support distributed transactions.

Так что теперь, вместо того, мы стараемся использовать SqlTransactions:

using(var db1 = new Db1Context()) 
using(var db2 = new Db2Context()) 
{ 
    if(db1.Database.Connection.State == ConnectionState.Closed) 
    { 
     //transaction can only work on open connection 
     db1.Database.Connection.Open(); 
    } 
    using(var tx = db1.Database.Connection.BeginTransaction()) 
    { 
     //ArgumentException on next line 
     db1.Users.Single(u => u.Email == oldEmail).Email = someEmail; 
     db2.Users.Single(u => u.Email == oldEmail).Email = someEmail; 
     db1.SaveChanges(); 
     db2.SaveChanges(); //what if this fails? 
    } 
} 

Это терпит неудачу с ошибкой:

ArgumentException: "EntityConnection can only be constructed with a closed DbConnection."

Так как мы можем это сделать?

ответ

0

Проще говоря, вы не можете. Вам необходимо реализовать 2PC для поддержки этого. Похоже, что у Azure есть очень серьезные ограничения.

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