Ich mache eine grundlegende Sache in C # (MS VS2008) und habe eine Frage mehr zum richtigen Design als zu spezifischem Code.
Ich erstelle eine Datentabelle und versuche dann, die Datentabelle von einem Datenleser zu laden (der auf einer gespeicherten SQL-Prozedur basiert). Ich frage mich, ob der effizienteste Weg zum Laden der Datentabelle darin besteht, eine while-Anweisung auszuführen, oder ob es einen besseren Weg gibt.
Für mich ist der einzige Nachteil, dass ich die Felder, die ich in meine while-Anweisung einfügen möchte, manuell eingeben muss, aber ich weiß auch nicht, wie ich das automatisieren kann, da ich nicht möchte, dass alle Felder aus dem SP nur diejenigen auswählen , aber das ist in meinen Augen keine große Sache.
Ich habe Codefragmente unterhalb der Gesamtheit meiner Aktivitäten eingefügt, obwohl der Code selbst für mich nicht bemerkenswert ist oder auch nur das, worüber ich frage. Moreso wundert sich über meine Methodik und werde später um Code-Hilfe bitten, wenn meine Strategie falsch / ineffizient ist.
var dtWriteoffUpload = new DataTable();
dtWriteoffUpload.Columns.Add("Unit");
dtWriteoffUpload.Columns.Add("Year");
dtWriteoffUpload.Columns.Add("Period");
dtWriteoffUpload.Columns.Add("Acct");
dtWriteoffUpload.Columns.Add("Descr");
dtWriteoffUpload.Columns.Add("DEFERRAL_TYPE");
dtWriteoffUpload.Columns.Add("NDC_Indicator");
dtWriteoffUpload.Columns.Add("Mgmt Cd");
dtWriteoffUpload.Columns.Add("Prod");
dtWriteoffUpload.Columns.Add("Node");
dtWriteoffUpload.Columns.Add("Curve_Family");
dtWriteoffUpload.Columns.Add("Sum Amount");
dtWriteoffUpload.Columns.Add("Base Curr");
dtWriteoffUpload.Columns.Add("Ledger");
cmd = util.SqlConn.CreateCommand();
cmd.CommandTimeout = 1000;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "proc_writeoff_data_details";
cmd.Parameters.Add("@whoAmI", SqlDbType.VarChar).Value =
WindowsIdentity.GetCurrent().Name;
cmd.Parameters.Add("@parmEndDateKey", SqlDbType.VarChar).Value = myMostRecentActualDate;
cmd.Parameters.Add("@countrykeys", SqlDbType.VarChar).Value = myCountryKey;
cmd.Parameters.Add("@nodekeys", SqlDbType.VarChar).Value = "1,2";
break;
dr = cmd.ExecuteReader();
while (dr.Read())
{
dtWriteoffUpload.Rows.Add(dr["country name"].ToString(), dr["country key"].ToString());
}
Antworten:
Sie können eine
DataTable
direkt von einem Datenleser laden, indem Sie eineLoad()
Methode akzeptieren, die eine akzeptiertIDataReader
.quelle
Bitte überprüfen Sie den folgenden Code. Automatisch wird es als DataTable konvertiert
quelle
dt.Load(reader)
funktioniert auch nicht immer - ich würde diese lästigenObject reference not set to an instance of an object
Fehler bekommen, wahrscheinlich wenn ich keine Zeilen zurück bekomme. So etwas Handbuch ist praktisch. Ich versuchte es und hatte diese loszuwerdencolumn.
in den LiniendtSchema
foreach
Schleife , weil sie sagte , es wäre eine illegale Besetzung zubool
auf(bool)drow["IsUnique"]
. Ich brauchte sie nicht, es reicht aus, die Spaltennamen zu erhalten, um die neuen zuDataTable
füllen. Dies hat mir geholfen, einds.Fill(adapter)
Problem zu lösen, bei dem ich keine große Tabelle laden konnteSELECT * FROM MyTable
.if (!dr.IsDBNull(i))
als nächstes in dieserfor
Schleife überprüfen . Dann machst du deinedataRow
Sachen. Aber dann brauchen Sie eineelse
, falls Sie eine Null finden. Wenn Sie dies tun, müssen Sie den Typ der Spalte herausfinden, die Sie hinzufügen, und die Null entsprechend zuweisen (dh Sie können zuweisen,String.Empty
ob sie vom Typ istSystem.String
, aber Sie müssen zuweisen,0
ob sieSystem.Int16
(Boolesches Feld) oderSystem.Decimal
.Wenn Sie versuchen, a zu laden
DataTable
, nutzen SieSqlDataAdapter
stattdessen Folgendes :Sie müssen nicht einmal die Spalten definieren. Erstellen Sie einfach das
DataTable
undFill
es.Hier
cString
ist Ihre Verbindungszeichenfolge undsql
der Befehl für gespeicherte Prozeduren.quelle
SqlDataReader
und diese mithilfe einer Schleife durch die Felder einlesen können.Wie Sagi in ihrer Antwort feststellte, ist DataTable.Load eine gute Lösung. Wenn Sie versuchen, mehrere Tabellen von einem einzigen Reader zu laden, müssen Sie DataReader.NextResult nicht aufrufen. Die DataTable.Load-Methode bringt den Leser auch zur nächsten Ergebnismenge (falls vorhanden).
quelle
Ich habe mich auch damit befasst und nach dem Vergleich der SqlDataAdapter.Fill-Methode mit den SqlDataReader.Load-Funktionen festgestellt, dass die SqlDataAdapter.Fill-Methode mit den von mir verwendeten Ergebnismengen mehr als doppelt so schnell ist
Verwendeter Code:
Ergebnisse:
Bei Leistungsproblemen ist die Verwendung der SqlDataAdapter.Fill-Methode weitaus effizienter. Also, es sei denn, Sie möchten sich in den Fuß schießen, verwenden Sie das. Es funktioniert schneller für kleine und große Datenmengen.
quelle