Meilleure façon d'obtenir une valeur unique à partir d'un DataTable?
J'ai un certain nombre de classes statiques contiennent des tables comme ceci:
using System;
using System.Data;
using System.Globalization;
public static class TableFoo
{
private static readonly DataTable ItemTable;
static TableFoo()
{
ItemTable = new DataTable("TableFoo") { Locale = CultureInfo.InvariantCulture };
ItemTable.Columns.Add("Id", typeof(int));
ItemTable.Columns["Id"].Unique = true;
ItemTable.Columns.Add("Description", typeof(string));
ItemTable.Columns.Add("Data1", typeof(int));
ItemTable.Columns.Add("Data2", typeof(double));
ItemTable.Rows.Add(0, "Item 1", 1, 1.0);
ItemTable.Rows.Add(1, "Item 2", 1, 1.0);
ItemTable.Rows.Add(2, "Item 3", 2, 0.75);
ItemTable.Rows.Add(3, "Item 4", 4, 0.25);
ItemTable.Rows.Add(4, "Item 5", 1, 1.0);
}
public static DataTable GetItemTable()
{
return ItemTable;
}
public static int Data1(int id)
{
DataRow[] dr = ItemTable.Select("Id = " + id);
if (dr.Length == 0)
{
throw new ArgumentOutOfRangeException("id", "Out of range.");
}
return (int)dr[0]["Data1"];
}
public static double Data2(int id)
{
DataRow[] dr = ItemTable.Select("Id = " + id);
if (dr.Length == 0)
{
throw new ArgumentOutOfRangeException("id", "Out of range.");
}
return (double)dr[0]["Data2"];
}
}
Est-il une meilleure façon d'écrire les Données 1 ou 2 méthodes qui retournent une valeur unique à partir d'une seule ligne qui correspond à l'id donné?
Mise à jour #1:
J'ai créé une méthode d'extension qui semble tout à fait agréable:
public static T FirstValue<T>(this DataTable datatable, int id, string fieldName)
{
try
{
return datatable.Rows.OfType<DataRow>().Where(row => (int)row["Id"] == id).Select(row => (T)row[fieldName]).First();
}
catch
{
throw new ArgumentOutOfRangeException("id", "Out of range.");
}
}
Mon Data1 méthode devient alors:
public static int Data1(int id)
{
return ItemTable.FirstValue<int>(id, "Data1");
}
et Data2 devient:
public static double Data2(int id)
{
return ItemTable.FirstValue<double>(id, "Data2");
}
Merci à tous de vos réponses, mais surtout à Anthony Pegram qui a donné à la très belle ligne de LINQ & Lambda code.
au moins, vous devriez refactoriser ces deux fonctions. La seule différence est la Données1 et Données2. Autre que cela ressemble à ce que je ferais avec un dataset non.
Je suis d'accord avec refactoring, mais ce était juste un exemple et Data1 ou Data2 peut faire des choses différentes en fonction de l'id sélectionné. Je pensais simplement qu'il peut y avoir une façon plus élégante de la sélection d'un seul élément.
Je suis d'accord avec refactoring, mais ce était juste un exemple et Data1 ou Data2 peut faire des choses différentes en fonction de l'id sélectionné. Je pensais simplement qu'il peut y avoir une façon plus élégante de la sélection d'un seul élément.
OriginalL'auteur Piers Myers | 2010-04-14
Vous devez vous connecter pour publier un commentaire.
Avez-vous envisagé d'utiliser Linq (ensembles de données)? Avec des expressions Linq vous n'auriez pas besoin de ces Données1 et Données2 fonctions à tous, depuis la recherche et le filtrage peut se produire en une seule ligne de code.
Exemple ajouté:
De prise de vue à partir de la hanche ici, merci donc de prendre avec un grain de sel (pas à proximité d'une IDE:)
Que deux lignes de code, mais vous pouvez facilement les envelopper l'obtention de l'Énumérable.
Je crois qu'il était allusion à quelque chose comme ceci
int data1 = dt.Rows.OfType<DataRow>().Where(row => (int)row["ID"] == 1).Select(row => (int)row["Data1"]).First(); double data2 = dt.Rows.OfType<DataRow>().Where(row => (int)row["ID"] == 1).Select(row => (double)row["Data2"]).First();
avec LINQ il semble que j'aurais besoin de créer un EnumerableRowCollection et puis itérer sur elle juste pour obtenir un seul rang, de la valeur
Merci Anthony Pegram, j'ai intégré votre réponse - voir ma mise à jour #1 ci-dessus. Je donnerais la tique à vous si vous aviez répondu à une réponse plutôt qu'un commentaire 🙂
Je suis heureux d'avoir contribué.
OriginalL'auteur Paul Sasik
Je suis un peu méfiant de votre architecture, mais jamais l'esprit que. Si vous voulez une fonction qui renvoie la première valeur de la première ligne d'un datatable qu'il va obtenir en quelque sorte, et que vous voulez fortement typé, je pense que la fonction ci-dessous sera une amélioration. Il vous permettrait d'avoir juste une fonction, réutilisable pour les différents types. Pour l'utiliser, il aurait lignes de code comme:
et si vous en avez envie:
La fonction gère tout type de terme générique de donner, de cordes, d'autres types de valeurs, les types nullables, les types de référence. Si le champ est null, la fonction renvoie la valeur "par défaut" de ce type ("" pour la chaîne). Si elle ne peut absolument pas faire la conversion, parce que vous avez demandé l'impossible à la conversion, il renvoie une erreur. Je l'ai fait une méthode d'extension sur le datarow type (appelé ValueOrDefault), et cette ventouse est vraiment pratique.
J'ai adapté ces données-outil de la méthode d'extension de la mine pour votre situation. Je suis dans une VB boutique, et je n'ai pas le temps de ré-écrire le tout en C#, mais vous pouvez le faire assez facilement.
OriginalL'auteur Patrick Karcher