Je fais une chose basique en C # (MS VS2008) et j'ai une question plus sur la conception appropriée que sur le code spécifique.
Je crée un datatable, puis j'essaie de charger le datatable à partir d'un datareader (qui est basé sur une procédure stockée SQL). Ce que je me demande, c'est si le moyen le plus efficace de charger la table de données est de faire une instruction while ou s'il existe un meilleur moyen.
Pour moi, le seul inconvénient est que je dois taper manuellement les champs que je veux ajouter dans ma déclaration while, mais je ne connais pas non plus le moyen d'automatiser cela de toute façon car je ne veux pas que tous les champs du SP, il suffit de les sélectionner , mais ce n'est pas très grave à mes yeux.
J'ai inclus des extraits de code sous la totalité de ce que je fais, bien que pour moi le code lui-même ne soit pas remarquable ni même ce que je demande. Moreso s'interrogeant sur ma méthodologie, je demanderai de l'aide au code plus tard si ma stratégie est erronée / inefficace.
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());
}
Réponses:
Vous pouvez charger un
DataTable
directement à partir d'un lecteur de données en utilisant laLoad()
méthode qui accepte unIDataReader
.la source
Veuillez vérifier le code ci-dessous. Il sera automatiquement converti en DataTable
la source
dt.Load(reader)
aussi ne fonctionne pas toujours - j'obtiendrais cesObject reference not set to an instance of an object
erreurs embêtantes , probablement quand je ne récupère aucune ligne. Quelque chose de manuel comme celui-ci est utile. Je l' ai essayé et a dû se débarrasser de cescolumn.
lignes dans ladtSchema
foreach
boucle , car il a dit qu'il était un casting illégalbool
sur(bool)drow["IsUnique"]
. Je n'en avais pas besoin, il suffit de récupérer les noms des colonnes pour remplir les nouvellesDataTable
. Cela a réussi à m'aider à surmonter unds.Fill(adapter)
problème avec lequel je ne pouvais pas charger une grande tableSELECT * FROM MyTable
.if (!dr.IsDBNull(i))
que la prochaine chose à l'intérieur de cettefor
boucle. Vous faites ensuite vosdataRow
affaires. Mais alors vous avez besoin d'unelse
sur cela, au cas où vous trouveriez un null. Si vous le faites, vous devez déterminer le type de la colonne que vous ajoutez et attribuer la valeur nulle en conséquence (c'est-à-dire que vous pouvez attribuerString.Empty
si elle est de typeSystem.String
, mais vous devez attribuer0
si c'estSystem.Int16
(champ booléen) ouSystem.Decimal
.Si vous essayez de charger un
DataTable
, utilisezSqlDataAdapter
plutôt le:Vous n'avez même pas besoin de définir les colonnes. Créez simplement le
DataTable
etFill
le.Voici
cString
votre chaîne de connexion etsql
la commande de procédure stockée.la source
SqlDataReader
et de les lire en utilisant une boucle à travers les champs.Comme Sagi l'a déclaré dans sa réponse, DataTable.Load est une bonne solution. Si vous essayez de charger plusieurs tables à partir d'un seul lecteur, vous n'avez pas besoin d'appeler DataReader.NextResult. La méthode DataTable.Load avance également le lecteur vers le jeu de résultats suivant (le cas échéant).
la source
J'ai également examiné cela et après avoir comparé la méthode SqlDataAdapter.Fill avec les fonctions SqlDataReader.Load, j'ai trouvé que la méthode SqlDataAdapter.Fill est plus de deux fois plus rapide avec les ensembles de résultats que j'utilise
Code utilisé:
Résultats:
Pour les problèmes de performances, l'utilisation de la méthode SqlDataAdapter.Fill est beaucoup plus efficace. Donc, à moins que vous ne vouliez vous tirer une balle dans le pied, utilisez-le. Il fonctionne plus rapidement pour les petits et grands ensembles de données.
la source