wake-up-neo.net

Konvertieren einer generischen Liste in ein Dataset in C #

Ich habe eine generische Liste von Objekten. Jedes Objekt verfügt über 9 String-Eigenschaften. Ich möchte diese Liste in einen Datensatz umwandeln, den ich an ein Datagridview übergeben kann ...... Was ist der beste Weg, dies zu tun?

17
Goober

Haben Sie versucht, die Liste direkt an das Datenfenster zu binden? Wenn nicht, probieren Sie es zuerst, weil es Ihnen viel Schmerz erspart. Wenn Sie es schon probiert haben, teilen Sie uns bitte mit, was falsch gelaufen ist, damit wir Sie besser beraten können. Die Datenbindung gibt Ihnen ein anderes Verhalten, je nachdem, welche Schnittstellen Ihr Datenobjekt implementiert. Wenn Ihr Datenobjekt beispielsweise nur IEnumerable (z. B. List) implementiert, erhalten Sie eine sehr einfache Einwegbindung. Wenn es jedoch auch IBindingList (z. B. BindingList, DataView) implementiert, erhalten Sie eine bidirektionale Bindung.

13

Ich entschuldige mich für die Beantwortung dieser Frage, aber ich dachte, es wäre der einfachste Weg, meinen endgültigen Code zu sehen. Es enthält Korrekturen für nullfähige Typen und Nullwerte :-)

    public static DataSet ToDataSet<T>(this IList<T> list)
    {
        Type elementType = typeof(T);
        DataSet ds = new DataSet();
        DataTable t = new DataTable();
        ds.Tables.Add(t);

        //add a column to table for each public property on T
        foreach (var propInfo in elementType.GetProperties())
        {
            Type ColType = Nullable.GetUnderlyingType(propInfo.PropertyType) ?? propInfo.PropertyType;

            t.Columns.Add(propInfo.Name, ColType);
        }

        //go through each property on T and add each value to the table
        foreach (T item in list)
        {
            DataRow row = t.NewRow();

            foreach (var propInfo in elementType.GetProperties())
            {
                row[propInfo.Name] = propInfo.GetValue(item, null) ?? DBNull.Value;
            }

            t.Rows.Add(row);
        }

        return ds;
    }
64
Bennett Dill

Es gibt einen Fehler mit dem Erweiterungscode von Lee. Sie müssen die neu aufgefüllte Zeile der Tabelle t hinzufügen, wenn Sie die Elemente in der Liste durchlaufen.

public static DataSet ToDataSet<T>(this IList<T> list) {

Type elementType = typeof(T);
DataSet ds = new DataSet();
DataTable t = new DataTable();
ds.Tables.Add(t);

//add a column to table for each public property on T
foreach(var propInfo in elementType.GetProperties())
{
    t.Columns.Add(propInfo.Name, propInfo.PropertyType);
}

//go through each property on T and add each value to the table
foreach(T item in list)
{
    DataRow row = t.NewRow();
    foreach(var propInfo in elementType.GetProperties())
    {
            row[propInfo.Name] = propInfo.GetValue(item, null);
    }

    //This line was missing:
    t.Rows.Add(row);
}


return ds;

}

12
user197292

Sie können eine Erweiterungsmethode erstellen, um alle Eigenschaftswerte durch Reflektion hinzuzufügen:

public static DataSet ToDataSet<T>(this IList<T> list)
{
    Type elementType = typeof(T);
    DataSet ds = new DataSet();
    DataTable t = new DataTable();
    ds.Tables.Add(t);

    //add a column to table for each public property on T
    foreach(var propInfo in elementType.GetProperties())
    {
        t.Columns.Add(propInfo.Name, propInfo.PropertyType);
    }

    //go through each property on T and add each value to the table
    foreach(T item in list)
    {
        DataRow row = t.NewRow();
        foreach(var propInfo in elementType.GetProperties())
        {
            row[propInfo.Name] = propInfo.GetValue(item, null);
        }
    }

    return ds;
}
5
Lee

Vielleicht möchten Sie auschecken 

http://www.codeproject.com/KB/vb/List2DataSet.aspx

Gibt einige verschiedene Ansätze.

3
Kelly Gendron

Brute-Force-Code zur Beantwortung Ihrer Frage:

DataTable dt = new DataTable();

//for each of your properties
dt.Columns.Add("PropertyOne", typeof(string));

foreach(Entity entity in entities)
{
  DataRow row = dt.NewRow();

  //foreach of your properties
  row["PropertyOne"] = entity.PropertyOne;

  dt.Rows.Add(row);
}

DataSet ds = new DataSet();
ds.Tables.Add(dt);
return ds;

Nun zur eigentlichen Frage. Warum möchtest du das tun? Wie bereits erwähnt, können Sie direkt an eine Objektliste binden. Vielleicht ein Reporting-Tool, das nur Datensätze verwendet? 

2
joshua.ewer

Ich habe selbst eine kleine Bibliothek geschrieben, um diese Aufgabe zu erledigen. Es verwendet Reflection nur zum ersten Mal, wenn ein Objekttyp in eine Datentabelle übersetzt werden soll. Es gibt eine Methode aus, die die gesamte Arbeit eines Objekttyps erledigt.

Es ist die schnellste Lösung, die ich kenne (deshalb habe ich sie entwickelt :-)). Sie finden es hier: ModelShredder bei GoogleCode

Derzeit wird nur die Übersetzung in eine DataTable unterstützt. Wie Sie Ihre Frage formuliert haben, sollte dies ausreichend sein. Der Support für DataSets (man denke an ein einfaches Reverse-ORM) ist bereits entwickelt. Wenn ich aus dem Urlaub zurückkomme, wird es in zwei Schwächen veröffentlicht :-)

2

Ich habe die akzeptierte Antwort durch die Verarbeitung von Werttypen geringfügig geändert. Dies ist mir aufgefallen, als ich Folgendes versucht habe, und da GetProperties () für Werttypen null ist, erhielt ich ein leeres Dataset. Ich weiß, dass dies nicht der Anwendungsfall für das OP ist, aber ich dachte, ich würde diese Änderung veröffentlichen, falls jemand anderes auf dasselbe stößt.

Enumerable.Range(1, 10).ToList().ToDataSet();

public static DataSet ToDataSet<T>(this IList<T> list)
{
    var elementType = typeof(T);
    var ds = new DataSet();
    var t = new DataTable();
    ds.Tables.Add(t);

    if (elementType.IsValueType)
    {
        var colType = Nullable.GetUnderlyingType(elementType) ?? elementType;
        t.Columns.Add(elementType.Name, colType);

    } else
    {
        //add a column to table for each public property on T
        foreach (var propInfo in elementType.GetProperties())
        {
            var colType = Nullable.GetUnderlyingType(propInfo.PropertyType) ?? propInfo.PropertyType;
            t.Columns.Add(propInfo.Name, colType);
        }
    }

    //go through each property on T and add each value to the table
    foreach (var item in list)
    {
        var row = t.NewRow();

        if (elementType.IsValueType)
        {
            row[elementType.Name] = item;
        }
        else
        {
            foreach (var propInfo in elementType.GetProperties())
            {
                row[propInfo.Name] = propInfo.GetValue(item, null) ?? DBNull.Value;
            }
        }
        t.Rows.Add(row);
    }

    return ds;
}
1
Richard Edwards

Ich habe diesen Code im Microsoft-Forum gefunden. Dies ist bisher eine der einfachsten Methoden, die leicht zu verstehen und zu verwenden sind. Das hat mir Stunden gespart, ich habe es als Erweiterungsmethode angepasst, ohne die eigentliche Methode zu ändern. Unten ist der Code. es bedarf keiner großen Erklärung. 

Sie können zwei Funktionssignaturen mit derselben Implementierung verwenden

1) public static DataSet ToDataSetFromObject (dieses Objekt dsCollection)

2) public static DataSet ToDataSetFromArrayOfObject (dieses Objekt [] arrCollection). Ich werde dieses zum Beispiel verwenden.

// <summary>
// Serialize Object to XML and then read it into a DataSet:
// </summary>
// <param name="arrCollection">Array of object</param>
// <returns>dataset</returns>

public static DataSet ToDataSetFromArrayOfObject( this object[] arrCollection)
{
    DataSet ds = new DataSet();
    try {
        XmlSerializer serializer = new XmlSerializer(arrCollection.GetType);
        System.IO.StringWriter sw = new System.IO.StringWriter();
        serializer.Serialize(sw, dsCollection);
        System.IO.StringReader reader = new System.IO.StringReader(sw.ToString());
        ds.ReadXml(reader);
    } catch (Exception ex) {
        throw (new Exception("Error While Converting Array of Object to Dataset."));
    }
    return ds;
}

Um diese Erweiterung im Code zu verwenden 

Country[] objArrayCountry = null;
objArrayCountry = ....;// populate your array
if ((objArrayCountry != null)) {
    dataset = objArrayCountry.ToDataSetFromArrayOfObject();
}
0

Eine Option wäre die Verwendung einer System.ComponenetModel.BindingList anstelle einer Liste.

Dadurch können Sie es direkt in einer DataGridView verwenden. Und im Gegensatz zu einer normalen System.Collections.Generic.List wird DataGridView bei Änderungen aktualisiert.

0
JDunkerley