Entwickler-Ecke
Datenbanken (inkl. ADO.NET) - Datenkapselung
ene - Fr 21.08.09 09:14
Titel: Datenkapselung
Angeregt durch JüTo's Einwurf zur Verwendung von Connection/Command/DataReader in einer using-Variante und
diesem Thread [
http://www.mycsharp.de/wbb2/thread.php?threadid=22354], stellt sich mir die Frage, wie man das am Sinnvollsten umsetzt. Ich verknote mir da regelnmäßg das Hirn bei.
Ist es also sinnvoll sich eine Klasse wie folgt zu erstellen:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| static class clsDB { public static string Connection = ""; public static string Command = "";
public static void Execute () { using (OleDbConnection con = new OleDbConnection(Connection)) using (OleDbCommand cmd = con.CreateCommand()) { cmd.CommandText = Command; con.Open(); cmd.ExecuteNonQuery(); } } } |
Für ein einfaches Execute kein Problem, bei einem Datareader, bin ich mir dort aber nicht so sicher:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| public static OleDbDataReader CreateRecordset () { using (OleDbConnection con = new OleDbConnection(Connection)) using (OleDbCommand cmd = con.CreateCommand()) { cmd.CommandText = Command; con.Open(); using (OleDbDataReader rs = cmd.ExecuteReader()) { return rs; } } } |
Der Aufruf wäre dann ja auch ein
using (OleDbDataReader dr = clsDB.CreateRecordset()). :gruebel:
JüTho - Fr 21.08.09 11:35
Hallo,
die Konstruktion ist im wesentlichen richtig (abgesehen davon, dass das Ganze als static-Bestandteile einer Klasse nicht so sinnvoll ist; aber ich nehme an, dass du das jetzt nur zu Demo-Zwecken so gebastelt hast).
Der DbDataReader macht es einem tatsächlich schwerer, weil er (wie in dem anderen Thread besprochen) die DbConnection häufig blockiert, bis er selbst geschlossen wird. Deshalb kann er auch nicht per return zurückgegeben werden, weil die DbConnection sofort geschlossen werden sollte und damit auch der Reader, der an diese DbConnection gebunden ist, verloren geht.
Die Lösung des Problems liegt darin, dass zwischen den verschiedenen Ebenen getrennt werden soll (am liebsten würde ich "muss" sagen, aber es kann abweichende Situationen geben): die Datenmenge im Arbeitsspeicher z.B. im typisierten DataSet auf der einen Seite, die Datenmenge auf der Festplatte (Datenbank) auf der anderen Seite. Die Verknüpfung zwischen beiden, z.B. eine Klasse für DbConnection und DbDataAdapter, füllt die Datenmenge im Arbeitsspeicher mit Werten - je nach Situation mit dem Rückgabewert einer DataTable oder mit einem einzelnen return-Wert oder mit einer List<T> als return-Wert oder mit Änderungen in einem DataSet oder was das Execute-Ergebnis sonst zurückliefert.
Ich hoffe, ich habe keine weitere Verwirrung hervorgerufen. Jürgen
PS. Lies übrigens auch einmal
NET Richtlinien für Namen [
http://msdn.microsoft.com/de-de/library/ms229002(VS.80).aspx] durch, vor allem hinsichtlich Groß- und Kleinschreibung.
ene - Fr 21.08.09 12:18
Moin Jürgen,
Danke für die Antwort. Die Benamsung ist schon toll. Neues Framework neue Benamsung. Reddick ist für mich oft sinnvoller und lesbarer. Teile davon wurden wenigstens übernommen.
B2T: Der Code ist pseudomäßig aufgesetzt, wobei Verbesserungen gerne angebracht werden dürfen ;) Die static-Variante war eigentlich nur für den einfachen Aufruf. Das Problem ist halt jetzt, dass in der Klasse der Reader erzeugt und gefüllt wird. Aber ich kann halt das Object nicht losgelößt weitergeben. Das würde mir das Interface ersparen. In VBA gibt es die Möglichkeit von "ungebundenen" Recordset, was für manche Daten sehr sinnvoll ist. Ein Beispiel
Quelltext
1: 2: 3: 4: 5: 6: 7:
| Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
rs.AcitveConnection = strConnection rs.Open "SELECT * FROM Tabelle" rs.ActiveConnection = Nothing |
Damit behält der Recordset die Daten, aber die Connection kann geschlossen werden und man kann damit tun, was man will. In dem o.a. Beispiel muss ich es ja in ein anderes Objekt überführen:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| public DataTable CreateRecordset () { using (OleDbConnection con = new OleDbConnection(Connection)) using (OleDbCommand cmd = con.CreateCommand()) { cmd.CommandText = Command; con.Open(); using (OleDbDataReader rs = cmd.ExecuteReader()) { DataTable dt = new DataTable(); dt.Load(rs); return dt; } } } |
Aber dadurch bin ich ja leider in der Rückgabe etwas eingeschränkter :(
Kha - Fr 21.08.09 18:15
ene hat folgendes geschrieben : |
Aber dadurch bin ich ja leider in der Rückgabe etwas eingeschränkter :( |
Was genau meinst du? Bzw. wo siehst du Unterschiede zwischen RecordSet und DataTable (kenne nur letztere ;) )?
ene - Mo 24.08.09 08:03
Ne, war ein Denkfehler von mir :( Der DataTable ist ja auch ein losgelößtes Set. Mal sehen, wie weit ich heute komme ohne mir das Hirn erneut zu verknoten :)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!