Eine kleine Geschichte der Transaktionen (4. Meine Transaktions-App)
Meine Transaktions-Test-Applikation ist über die Jahre gewachsen, weil ich immer weitere Möglichkeiten, wie man Transaktionen programmieren kann eingebaut habe. Angefangen habe ich damit, weil ich testen wollte wie sich die neue .NET Welt im Vergleich zur alten COM+ Welt im Sinne von Performance verhält. Datengrundlage ist eine sehr einfache Datenbank, die mein noch einfacheres Modell einer Bank darstellen soll.
NameOfAccount |
AccountNo |
AccountBalance |
Martin |
1 |
100416 |
Andreas |
2 |
100340 |
Klaus |
3 |
99580 |
Also wir haben Personen, die eine Kontonummer haben und einen gewissen Betrag an Geld auf dem Konto. Für eine Überweisung (Transaktion) ist es also notwendig zwei Updates auf die Tabelle auszuführen. Die Erste um den Betrag bei einem Konto abzuziehen und die Zweite um denselben Betrag bei dem anderen Konto gutzuschreiben. Das Ganze muss eine Transaktion sein, denn wenn nach dem “Abbuchen” was schiefgeht und der Update mit der “Gutschrift” nicht mehr ausgeführt wird ist die Kohle weg. Oder besser gesagt die Bank hat es, aber das ist ja fast dasselbe .
Genutzt wird in allen Fällen im Prinzip eine Stored Procedure, die beide Updates ausführt. Für die Fall Nr.4 wird eine Stored Procedure verwendet die in T-SQL den Transaktionskontext direkt in der DB angelegt.
Noch ein Hinweis. Es geht hier nicht um die Performance des SQL Servers, sondern es geht um den Overhead den Datenbankzugriffstechnologien und die verschiedenen Aufrufarten beim Benutzen von Transaktionen erzeugen!
Als nächstes eine kurze Beschreibung der verwendeten technischen Komponenten um die Transaktion über die beiden Datenbankupdates auszuführen.
-
- C++ OLE DB ATL COM+ Komponente
In der Zeit vor .NET, ja die gab es wirklich, war C++ in Kombination mit OLE DB Templates in ATL (Active Template Library) so ziemlich die “schnellste” Datenbankzugriffstechnologie. Für den Transaktionskontext wird COM+ als Container benutzt. Da es sich auch um eine Serverprozess-Komponente handelt, wird der Transaktionskontext über den DTC (Distributed Transaction Coordinator) bereitgestellt. Im folgenden Bild ist die Konfiguration im COM+ Explorer abgebildet. Der Client ist ein .NET Client der also über COM-InterOp die in einer COM+ Applikation “gehostedete” COM-Komponente aufruft.
- .NET Serviced Component also COM+ Komponente in C# .NET geschrieben mit COM+ Transaktionskontext
Im Namespace System.EnterpriseServices wurden in .NET die Services von COM+ für die .NET Welt zugänglich gemacht. Diese Komponente ist also im Prinzip dasselbe wie in 1. nur jetzt mit .NET als Serviced Component implementiert. Also in C# und .NET entwickelt, aber in einem COM+ Container (Application) gehosted. Der Client ist derselbe .NET Client wie bei 1. der also in diesem Fall über COM-InterOp die in einer COM+ Application “gehostedete” .NET-Komponente aufruft.
- C++ OLE DB ATL COM+ Komponente
-
- .NET Serviced Component also COM+ Komponente in C# .NET geschrieben mit ADO.NET Transaktionskontext
Dasselbe Prinzip wie bei 2. bis auf den Unterschied, dass der Transaktionskontext nicht über COM+ bzw. den DTC bereitgestellt wird, sondern über die API welche über ADO.NET verfügbar ist.
- .NET Serviced Component also COM+ Komponente in C# .NET geschrieben mit ADO.NET Transaktionskontext
-
- .NET Serviced Component also COM+ Komponente in C# .NET geschrieben mit Transaktionskontext in Stored Procedure
Im Prinzip auch wieder wie 2. und 3. nur das der Transaktionskontext direkt in der DB innerhalb der Stored Procedure erstellt wird.
- .NET Serviced Component also COM+ Komponente in C# .NET geschrieben mit Transaktionskontext in Stored Procedure
-
- ASMX Web Service der die .NET Komponente aus 4. benutzt.
Vor .NET 2.0, also als es WCF (Windows Communication Foundation) usw. noch nicht gab war SMAX aus dem ASP.NET Namespace die gängigste Methode Web Services zu implementieren, die somit auch im IIS gehosted werden. Der Web Service benutzt die Komponente aus 4. die in COM+ liegt und eine Stored Procedure für die Transaction verwendet.
- ASMX Web Service der die .NET Komponente aus 4. benutzt.
-
- WCF Komponente “hosted” im IIS (auto-enlist) aufgerufen über HTTP Web Service
Hier kommt zum ersten Mal WCF zu Einsatz, also auch kein COM+ mehr irgendwie beteiligt. Der Namespace in .NET WCF für Transaktionen heißt : System.ServiceModel gesteuert wir das Verhalten hier über Attribute gesteuert z.B. wird das Isolation Level so eingestellt:
[ServiceBehavior(TransactionIsolationLevel = System.Transactions.IsolationLevel.Serializable ]
Der Aufruf geht über HTTP und die Komponente wird im IIS bereitgestellt. - WCF Komponente “hosted” in eigenem Prozess aufgerufen über TCP Web Service
Jetzt wird nicht der IIS benutzt sondern eine eigene klein App, die den Web Service über TCP bereitstellt. Damit wird der Web Service natürlich über TCP aufgerufen, wobei nicht der XML Serializer benutzt wird sondern ein Binary Serializer.
- WCF Komponente “hosted” im IIS (auto-enlist) aufgerufen über HTTP Web Service
-
- WCF Komponente “hosted” in IIS über WAS Hosting aufgerufen über TCP Web Service
Dieselbe Komponente wie bei 7. jetzt aber mit WAS Hosting (Windows Activation Services) im IIS, Dies erlaubt es die Komponente im IIS zu hosten und per TCP aufzurufen, was wie bei 7. den XML Serializer vermeidet.
- WCF Komponente “hosted” in IIS über WAS Hosting aufgerufen über TCP Web Service
-
- WCF Komponente mit Entity Framework als OO Mapper ohne Stored Procedure WAS Hosting TCP Web Service
In diesem Fall wird das Entity Framework so eingesetzt, wie man es typischerweise ohne besondere weitere Programmierung tun würde. Das heisst es wird dem Framework überlassen die entsprechenden SQL Statements zusammenzubauen und auszuführen. Dies bedeutet natürlich einen Nachteil gegenüber der Verwendung von einer Stored Procedure, die vorkompiliert im SQL Server bereitgestellt ist.
- WCF Komponente mit Entity Framework als OO Mapper ohne Stored Procedure WAS Hosting TCP Web Service
-
- WCF Komponente mit Entity Framework als OO Mapper mit Stored Procedure WAS Hosting TCP Web Service
Im zweiten Beispiel mit dem Entity Framework wird jetzt ebenfalls die Stored Procedure verwendet, um zu sehen welchen Overhead das Entity Framework als OO Mapper dann noch erzeugt.
- WCF Komponente mit Entity Framework als OO Mapper mit Stored Procedure WAS Hosting TCP Web Service
Die Ergebnisse:
Erläuterungen zu den Ergebnissen:
Als erstes möchte ich anmerken, dass in den ersten Versionen von .NET also 1.0.und 2.0 die C++ ATL Variante schneller war als .NET in COM+. Das hat sich deutlich geändert. Man sieht also, dass die .NET DB Provider im Sinne von Performance deutlich besser sind als die “alte” OLE DB Welt. Weiterhin ist wie zu erwarten Nummer 3 schneller als Nummer 2, da der Transaktionskontext nicht global über den DTC bereitgestellt werden muss sondern nur vom Client zur DB über ADO.NET aufgebaut werden muss. Die Nummer 4 ist dann logischerweise noch etwas flotter unterwegs, da der Transaktionskontext direkt im SQL Server für eine Stored Procedure erstellt wird.
Jetzt kommen wir zu den Web Service Technologien, wobei natürlich sofort ins Auge sticht wie schlecht die ASMX Web Service Implementierung im Vergleich zu WCF abschneidet. Erwartungsgemäß ist auch so, dass die Verwendung von TCP als Protokoll und den Binary Serializer eine deutliche Verbessrung gegenüber der Verwendung von HTTP und dem XML Serializer bringt. Man sieht auch dass man den IIS als Host nutzt und mit TCP und WAS Hosting arbeitet, die Vorteile vom IIS nutzen kann ohne hier Nachteile in der Performance zu bekommen, sogar im Gegenteil.
Die Verwendung des Entity Framework macht den Zugriff auf die Datenbank zwar komfortabel, aber man bezahlt einen Preis dafür. Aber auch hier kann man für immer wieder kehrende Aufgaben Stored Procedures verwenden, um die Performance deutlich zu verbessern.
Viele Grüße
Euer Martin