verwendetes Datenbanksystem: <MS SQL 2005>
Hallo Leute,
für eine mandantenübergreifende Buchung möchte ich, dass sich eine Transaktion über 2 Datenbanken erstreckt. Laut Doku sollte das gehen.
Beide Datenbanken laufen auf der gleichen SQL-Server-Instanz.
Mein Code wirft leider einen Fehler :
bool error = false;
DataSet ds1 = new DataSet();
DataSet ds2 = new DataSet();
DbConnection conn1 = db.CreateConnection(db1);
DbConnection conn2 = db.CreateConnection(db2);
conn1.Open();
conn2.Open();
DbTransaction trans = conn1.BeginTransaction();
DbDataAdapter da1 = db.CreateDataAdapter();
DbDataAdapter da2 = db.CreateDataAdapter();
DbCommand cmd1 = db.CreateCommand();
DbCommand cmd2 = db.CreateCommand();
cmd1.Connection = conn1;
cmd2.Connection = conn2;
cmd1.Transaction = trans;
cmd2.Transaction = trans;
cmd1.CommandText = "select * from ar where ar_nr = '1'";
cmd2.CommandText = "select * from ar where ar_nr = '1'";
da1.SelectCommand = cmd1;
da2.SelectCommand = cmd2;
da1.Fill(ds1, "ar");
da2.Fill(ds2, "ar"); // Hier kommt der Fehler "Die Transaktion ist entweder nicht mit der aktuellen Verbindung verknüpft oder wurde abgeschlossen."
ds1.Tables["ar"].Rows[0]["ar_bez2"] = "Trans 1 " + DateTime.Now.ToString();
ds2.Tables["ar"].Rows[0]["ar_bez2"] = "Trans 2 " + DateTime.Now.ToString();
da1.Update(ds1, "ar");
da2.Update(ds2, "ar");
if (error) trans.Rollback();
else trans.Commit();
conn1.Close();
conn2.Close();
Der Fehler tritt bei da2.Fill() auf : > Fehlermeldung:
"Die Transaktion ist entweder nicht mit der aktuellen Verbindung verknüpft oder wurde abgeschlossen."
Hinweis : db.CreateConnection() legt eine Connection an, db.CreateDataAdapter() einen DbDataAdapter und db.CreateCommand() ein DbCommand.
Wie könnte der Code lauten damit er funktioniert ?
Muss ich MSDTC einrichten ? Laut MSDN nicht nötig.
Funktioniert die datenbankübergreifende Transaktion vielleicht nur mit TransactionScope ? Ich würde gerne bei den normalen Transactions bleiben.
Grüße Bernd
Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3
Eventuell hilft dir ein TransactionScope weiter:
using (TransactionScope scope = new TransactionScope())
{
// .. Datenbanken und kram code ..
scope.Complete();
}
der sollte automatisch zurückrollen
Der Vorteil der Klugheit liegt darin, dass man sich dumm stellen kann - umgekehrt ist das schon schwieriger (K. Tucholsky)
Das Problem mit Internet-Zitaten ist, dass sie oftmals zu unrecht als authentisch angenommen werden. (K. Adenauer)
Dazu auch ein Beispiel auf der MSDN Seite: System.Transactions Integration with SQL Server (ADO.NET)
Lg, XXX
Anmerkung:
Alternativ kannst du dir anschauen, wie ein 3 Phasen-Commit-Protokoll aussieht und selbiges nachbilden.
Allerdings ist das wohl komplizierter 😉
Der Vorteil der Klugheit liegt darin, dass man sich dumm stellen kann - umgekehrt ist das schon schwieriger (K. Tucholsky)
Das Problem mit Internet-Zitaten ist, dass sie oftmals zu unrecht als authentisch angenommen werden. (K. Adenauer)
Hallo,
danke für die Tipps.
Mit TransactionScope tut es.
Ich musste zwar MSDTC einrichten, aber das ging schnell.
Jetzt muss ich kontrollieren ob TransactionScope auch unter allen Bedingungen tut und wie sich der Resourcenverbrauch erhöht (Zeit, Speicher).
Hinweis : Es muss ein Verweis auf die System.Transactions.dll gesetzt werden.
Anmerkung:
Alternativ kannst du dir anschauen, wie ein 3 Phasen-Commit-Protokoll aussieht und selbiges nachbilden. Allerdings ist das wohl komplizierter 😉
Nein, lieber nicht !
Grüße Bernd
Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3