We have a scenario to save two entities from two contexts in single transaction.
Step 1 - SetTransaction(firstContext, true);
Step 2 - Save first entity using firstContext.
Step 3 - SetTransaction(secondContext, false);
Step 4 - Save second entity using secondContext
Step 5 - finally commit the transaction.
void function SetTransaction(context, startNewTransaction)
{
var currentContext = firstContext;
if (startNewTransaction)
{
var connection = currentContext.GetConnection();
connection.Open();
this.dbTransaction = connection.BeginTransaction();
}
if (this.dbTransaction != null)
{
currentContext.UseTransaction(dbTransaction);
}
}
While executing Step 3, currentContext.UseTransaction(dbTransaction); line throws the exception as " The transaction passed in is not associated with the current connection. Only transactions associated with the current connection may be used "
Please suggest how to resolve.
Venkat.
Use the TransactionScope
. EF will automatically enlist in a running transaction-scope.
It will require that your connectionstrings are identical .
using (var scope = new TransactionScope()) {
// Save entity in context A
using (var contextA = new ContextA()) {
contextA.Save(...);
contextA.SaveChanges;
}
// Save entity in context B
using (var contextB = new ContextB()) {
contextB.Save(...);
contextB.SaveChanges;
}
// Commit tx-scope
scope.Complete();
}
Using TransactionScope is not recommanded from EF 6 onward. So use:
using (var conn = new SqlConnection("..."))
{
conn.Open();
using (var sqlTxn = conn.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
{
try
{
using (var contextA = new ContextA(conn, contextOwnsConnection: false))
{
contextA.Database.UseTransaction(sqlTxn);
contextA.Save(...);
contextA.SaveChanges();
}
using (var contextB = new ContextB(conn, contextOwnsConnection: false))
{
contextB.Database.UseTransaction(sqlTxn);
contextB.Save(...);
contextB.SaveChanges();
}
sqlTxn.Commit();
}
catch (Exception)
{
sqlTxn.Rollback();
}
}
}
}
Edit: If your dbContext does not have required constructor, You can add another constructor as follow:
public ContextA(): base("name=ConnectionString")
{
}
public ContextA(DbConnection connection) : base(connection, false)
{
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.