Öffnen und schließen einer Datenbank-Verbindung innerhalb einer Transaktion
Habe ich die Daten zugreifen Teil unseres Frameworks, so dass jedes mal, wenn ein business-Objekt (BO) braucht, um mit der Datenbank interagieren, würde es haben, eine Verbindung zu öffnen, rufen Sie den data-access-layer (für die Abfrage ausführen), und anschließend die Verbindung schließen. Dann, wenn es benötigt wird, um in einer Transaktion ausgeführt werden, es würde öffnen die Verbindung, starten Sie die Transaktion aufrufen, die Datenzugriffsschicht (data access layer, um die Abfrage auszuführen) und dann commit der Transaktion, schließen Sie die Transaktion, und schließlich die Verbindung schließen.
Habe ich es auf diese Weise in die Denkweise des "öffnen spät, früh schließen"... aber was ist, wenn ich brauchte, um Anruf andere BOs zum übermitteln von Daten in einer einzelnen Transaktion? Gibt es eine bessere Art das zu handhaben, öffnen und schließen von verbindungen sowie die Arbeit mit Transaktionen?
Ich bin ein rookie in der Gestaltung-Anwendung-Architektur, so dass ich hoffe, ich Tue es nicht falsch... jede Hilfe ist willkommen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn ein bestimmtes business-Objekt muss für die Ausführung verschiedener Methoden in einer Transaktion, verwenden Sie eine
TransactionScope
etwa so:Wenn die Objekte eine exception wirft, wird es ein rollback für die Transaktion.
Sehen die MSDN Referenz-Seite für
TransactionScope
für mehr.TransactionScope
ist, das die Klasse hier, mit den OP ' s im aktuellen design wird es sich in einer verteilten Transaktion oder möglicherweise eine Ausnahme ausgelöst, wenn der MSDTC ist deaktiviert oder gesperrt. Es ist wahrscheinlich nicht das gewünschte Ergebnis.IDbConnection.Close
: "DieClose
Methode Rollback alle ausstehenden Transaktionen." OTOH,SqlConnection.Close
, die implementiert, dass die interface-Methode: "Transaktionen gestartet durchSystem.Transactions
sind gesteuert durch dieSystem.Transactions
Infrastruktur, und sind nicht betroffen vonSqlConnection.Close
." SoTransactionScope
funktioniert nur für SQL-Server?childObj.Save()
so viele Male? Diese sollen, werden Anrufe an unterschiedlichen Objekten (childObjA
,childObjB
, ...)?Beim higher-level Abstraktionen abhängen, Low-level-Abstraktionen (wie business-Logik-Klassen je nach Daten-verbindungen), ist es üblich, zur Stromversorgung der Low-level-Abstraktionen durch den Konstruktor. Die Technik nennt sich constructor injection:
Dies ermöglicht Ihnen, code zu schreiben, gegen die Dienste, die der folgenden ähnelt:
Welche ist am ehesten zu werden, was Sie wollen, am Ende - die Fähigkeit zu teilen, eine Verbindung unter vielen services.
Hilft dies auch entkoppeln Ihre Dienste von den Einzelheiten der Implementierung der Daten-Verbindung. So, wenn Sie wollen, etwas zu tun, wie das ändern der Anschluss-Einstellungen unter bestimmten Umständen, die Sie nicht haben zu Graben, in die details zu 50 verschiedene services, müssen Sie nur ändern, das eine Zeile code erstellt die Verbindung.
Eins noch: Wenn du gehst zu verwenden, die
TransactionScope
, stellen Sie sicher, dass SieTransaction Binding=Explicit Unbind
um die Verbindung Zeichenfolge, ansonsten ist es tatsächlich möglich, am Ende mit inkonsistenten Daten wenn eine Transaktion mal aus.Wie von anderen erwähnt,
TransactionScope
ist der Weg zu gehen.Wenn Sie mit SQL Server 2008 und .NET 3.5, ich würde ändern das design der business-Objekt-Kontrolle der Transaktion und lassen Sie das öffnen und schließen der Verbindung auf die Daten-Schicht.
Mit Verbindungs-pooling auf, Sie werden nicht tatsächlich den Verarbeitungsaufwand, der Eröffnung einer physischen Datenbank-Verbindung und Ihre verbindungen werden nur geöffnet, wenn die Durchführung der Arbeit. Da (habe ich angenommen) Sie haben SQL Server 2008 mit .NET 3.5 wird Ihre Transaktion nicht eskalieren zu einer verteilten Transaktion (es sei denn, Sie öffnen mehrere verbindungen zur gleichen Zeit), so erhalten Sie das beste aus beiden Welten.
Dann könnten Sie schreiben, Ihre business-Objekt wie folgt:
Dies verhindert, dass pass Verbindungszeichenfolgen rund um alle business-Objekte und macht die Koordinierung der Transaktionen leicht.
Update
Die Schönheit des Systems.Transaktionen ist, dass alle Transaktionen werden für Sie verwaltet unabhängig von der Verbindung, die Sie verwenden. Sie einfach erklären, eine TransactionScope-und alle Datenbank-Zugriff innerhalb des TransactionScope-auftreten innerhalb einer einzelnen Transaktion (es sei denn Sie verlangen ansonsten mit verschiedenen TransactionScope-Einstellungen).
In der Vergangenheit (SQL Server 2005 .NET 2.0), wenn Sie geöffnet und geschlossen und dann geöffnet und geschlossen einem anderen Anschluss (auch mit der gleichen connection string) und dann die Transaktion wurde gefördert durch ein Leichtes Transaktion zu einer Verteilten Transaktion. Dies war unerwünscht, da die Leistung leidet (Mitteilung MSDTC ist aus der Prozess-und der zwei-Phasen-commit-Protokoll) und MSDTC kann ein Schmerz, um zu konfigurieren, in vielen Produktionsumgebungen (firewalls und security).
Mit SQL Server 2008 und .NET 3.5 haben Sie die Möglichkeit Hinzugefügt, um zu vermeiden, diese Aktion beim öffnen und schließen mehrere verbindungen mit dem gleichen connection string in einer einzigen Transaktion. Für eine wirklich gute Erklärung, was Sie Taten, sehen Erweiterung Leichte Transaktionen in "SqlClient".
Update 2
Transaktionen mit Oracle 10g wird ordnungsgemäß mit TransactionScope. Und es sieht aus wie ODP.NET unterstützt Leichtbau-Transaktionen (das ist schön). Leider, ich denke, dass die Förderung zu einer verteilten Transaktion auftreten wird mit dem schließen und öffnen der verbindungen.
Wenn Sie vermeiden wollen, dass eine verteilte Transaktion, die Sie nicht passieren konnten, die Verbindung zu jedem Methodenaufruf/Business-Objekt. Wenn Sie nicht wollen, eine Verbindung um, könnte man eine ConnectionScope Klasse, die die Verbindung geöffnet hält für den thread. Eine alternative dazu wäre die Verwendung von Enterprise Library 3.0 (und höher) Data Access Application Block. Die Daten, die den Zugriff Blockieren können feststellen, dass eine Transaktion im Gange ist, und die dieselbe Verbindung verwenden zu vermeiden, die eine verteilte Transaktion.
Klingt wie Sie haben die richtige Idee. Wenn mehrere BOs beteiligt werden müssen, dann ist einer von Ihnen muss ein "controller" — es soll das öffnen und schließen der Verbindung, und geben es an andere weiter. Oder einige "wrapper" - Objekt behandeln könne, die Verbindung und übergeben es an jeden der BOs. Ihr BOs kann entworfen werden müssen, um den Betrieb sowohl auf Ihre eigenen (die Bearbeitung Ihrer eigenen Verbindung), und zu akzeptieren, eine vorhandene Verbindung von außen.
Sind Sie wahrscheinlich auf der Suche für die Einheit der Arbeit Muster und Registrierung Muster. Diese beiden Muster können im Konzert zu trennen, die Anliegen zu finden, business-Objekte und tracking Sie Sie für später verpflichten, Ihre Daten zu speichern, wie eine Transaktion.
Ich würde auch einen Blick in Objekt-Relationalen Mapping oder ORM. ORM ist eine höhere Ebene, die Zusammensetzung der Einheit von Arbeit, registry, Beharrlichkeit Ignoranz und andere Muster, die bietet eine sehr saubere Trennung der Geschäftslogik von der Persistenz-Logik. Mit und ORM, können Sie in der Regel beseitigen die Notwendigkeit, zu schreiben gespeicherte Prozeduren, benutzerdefinierte bauen DAL, etc. Der ORM kümmert sich um Ihre Persistenz Anliegen für Sie, damit Sie sich auf die business-Logik, die getan werden muss.
Da du mit C# und .NET, ich würde in Entity Framework (v4, nicht verwenden, v1), oder LINQ to SQL. Beide sind ODER Mapper, die mit dem .NET framework von v3.5 und ab. LINQ to SQL ist ein sehr einfaches und gut verarbeitetes ORM, das sollte erhalten Sie gehen sehr schnell. Entity Framework ist viel reicher ORM, die ist auch sehr gut nachgerüstet (besser als LINQ to SQL) und bietet deutlich mehr Funktionalität. Es gibt auch third-party ORM ' s, die den job tun können, einschließlich eines freien namens NHibernate. Es ist zwar nicht so gut gefertigt wie die Microsoft ORM ' s, NHibernate ist eine sehr ausgereifte open-source-ORM mit einer großen community folgenden.
Wenn ein ORM ist nicht eine Möglichkeit, dann würde ich schauen in Einheit der Arbeit, Registrierung (oder Repository), die Beharrlichkeit der Ignoranz, Trennung der Anliegen, Einzelne Verantwortung und andere Verwandte Muster.