web-dev-qa-db-fra.com

Transformez une table de données en dictionnaire C #

Je veux savoir comment transformer un DataTable en un dictionnaire. J'ai fait quelque chose comme ça.

using System.Linq;

internal Dictionary<string,object> GetDict(DataTable dt)
{
    return dt.AsEnumerable()
      .ToDictionary<string, object>(row => row.Field<string>(0),
                                row => row.Field<object>(1));
}

Mais je reçois:

System.Data.EnumerableRowCollection ne contient pas de définition pour 'ToDictionary' et la meilleure surcharge d'extension de méthode 'System.Linq.Parallel.Enumerable.ToDictionary (System.Linq.ParallelQuery, System.Func, System.Collections.Generic.IEqualityComrparerer)' a des arguments invalides

Comment puis-je résoudre ça?

Merci

30
Maximus Decimus

La méthode générique ToDictionary a 3 paramètres. Vous en avez laissé un, donc il ne sait pas quoi faire. Si vous souhaitez spécifier tous les paramètres, ce serait <DataRow, string, object>.

internal Dictionary<string,object> GetDict(DataTable dt)
{
    return dt.AsEnumerable()
      .ToDictionary<DataRow, string, object>(row => row.Field<string>(0),
                                row => row.Field<object>(1));
}

Bien sûr, si vous les laissez désactivés, le compilateur est en mesure d'inférer les types, de sorte que vous n'obtenez pas l'erreur.

71
cadrell0

Toutes les réponses précédentes ne m'ont pas aidé, alors j'ai fait ceci:

myList = dt.AsEnumerable()
.ToDictionary<DataRow, string, string>(row => row[0].ToString(),
                                       row => row[1].ToString()); 

et cela a très bien fonctionné!

14
ParPar

je préfère cette méthode:

public static List<Dictionary<string, string>> GetDataTableDictionaryList(DataTable dt)
{
    return dt.AsEnumerable().Select(
        row => dt.Columns.Cast<DataColumn>().ToDictionary(
            column => column.ColumnName,
            column => row[column].ToString()
        )).ToList();
}

la raison en est que ce code peut également traiter des booléens ou d'autres types de données en appelant la méthode ToString.

Notez que cela renvoie une liste de dictionnaires, vous pouvez le modifier en un dictionnaire de dictionnaires si vous avez une clé pour chaque ligne.

itérer sur une colonne booléenne pourrait ressembler à ceci:

var list = GetDataTableDictionaryList(dt);

foreach (var row in list)
{
    if (row["Selected"].Equals("true", StringComparison.OrdinalIgnoreCase))
    {
        // do something
    }
}
6
Yakir Manor

ToDictionary attend le IEnumberable<T> comme premier type ... vous lui disiez que c'était une chaîne qui ne va pas c'est IEnumerable<DataRow>

Cela devient confus en spécifiant les types ... essayez ceci ...

internal Dictionary<string,object> GetDict(DataTable dt)
{
    return dt.AsEnumerable()
      .ToDictionary(row => row.Field<string>(0),
                                row => row.Field<object>(1));
}
6
Kevin

je crois que ceci vous aidera:

            DataTable dt = new DataTable();
            dt.Columns.Add("Column1");
            dt.Columns.Add("Column2");
            dt.Rows.Add(1, "first");
            dt.Rows.Add(2, "second");
            var dictionary = dt.Rows.OfType<DataRow>().ToDictionary(d => d.Field<string>(0), v => v.Field<object>(1));
2
terrybozzio

J'ai trouvé la solution mais je ne sais pas pourquoi. J'ai édité ma question en complétant le code juste pour être clair sur ce que je faisais et je l'ai changé

    internal Dictionary<string, object> GetDict(DataTable dt)
    {
        Dictionary<String, Object> dic = dt.AsEnumerable().ToDictionary(row => row.Field<String>(0), row => row.Field<Object>(1));
        return dic;
    }
1
Maximus Decimus

Les solutions données supposent seulement 2 colonnes. Si vous souhaitez une représentation multi-colonnes, vous avez besoin d'une liste de dictionnaires

class Program
{
    static void Main(string[] args)
    {
        DataTable dt = new DataTable();
        dt.Columns.Add("Column1");
        dt.Columns.Add("Column2");
        dt.Columns.Add("Column3");
        dt.Rows.Add(1, "first", "A");
        dt.Rows.Add(2, "second", "B");

        var dictTable = DataTableToDictionaryList(dt);
        var rowCount = dictTable.Count;
        var colCount = dictTable[0].Count;

        //Linq version
        var dictTableFromLinq = dt.AsEnumerable().Select(
                // ...then iterate through the columns...  
                row => dt.Columns.Cast<DataColumn>().ToDictionary(
                    // ...and find the key value pairs for the dictionary  
                    column => column.ColumnName,    // Key  
                    column => row[column] as string // Value  
                    )
                ).ToList();
    }

    public static List<Dictionary<string, object>> DataTableToDictionaryList(DataTable dt)
    {
        var result = new List<Dictionary<string, object>>();
        //or var result = new List<Dictionary<string, string>>();

        foreach (DataRow row in dt.Rows)
        {
            var dictRow = new Dictionary<string, object>();
            foreach (DataColumn col in dt.Columns)
            {
                dictRow.Add(col.ColumnName, row[col]);
                //or dictRow.Add(col.ColumnName, row[col].ToString());
            }

            result.Add(dictRow);
        }

        return result;
    }
}  
0
Pawel Cioch