Итак, у меня есть две базы данных ... база данных 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."
Так как мы можем это сделать?