Jak przekształcić listę w zbiór danych?

Biorąc pod uwagę listę obiektów, muszę przekształcić ją w zbiór danych, w którym każda pozycja na liście jest reprezentowana przez wiersz, a każda właściwość jest kolumną w wierszu. Ten zestaw danych zostanie następnie przekazany do Aspose.Komórki działają w celu utworzenia dokumentu Excel jako raportu.

Powiedzmy, że mam:

public class Record
{
   public int ID { get; set; }
   public bool Status { get; set; }
   public string Message { get; set; }
}

Biorąc pod uwagę rekordy listy, jak przekształcić je w zbiór danych w następujący sposób:

ID Status Message
1  true   "message" 
2  false  "message2" 
3  true   "message3" 
...

W tej chwili jedyną rzeczą, o której mogę myśleć, jest to, że "follows": {]}

DataSet ds = new DataSet
ds.Tables.Add();
ds.Tables[0].Add("ID", typeof(int));    
ds.Tables[0].Add("Status", typeof(bool));
ds.Tables[0].Add("Message", typeof(string));

foreach(Record record in records)
{
    ds.Tables[0].Rows.Add(record.ID, record.Status, record.Message);
}

Ale w ten sposób pozostawia mi myślenie, że musi być lepszy sposób, ponieważ przynajmniej jeśli nowe właściwości są dodawane do rekordu, to nie pojawią się w zbiorze danych...ale jednocześnie pozwala mi kontrolować kolejność dodawania każdej właściwości do wiersza.

Czy ktoś zna lepszy sposób na to?
Author: mezoid, 2009-02-07

5 answers

Możesz to zrobić poprzez odbicie i generyki, sprawdzając właściwości podstawowego typu.

Rozważ tę metodę rozszerzenia, której używam:

    public static DataTable ToDataTable<T>(this IEnumerable<T> collection)
    {
        DataTable dt = new DataTable("DataTable");
        Type t = typeof(T);
        PropertyInfo[] pia = t.GetProperties();

        //Inspect the properties and create the columns in the DataTable
        foreach (PropertyInfo pi in pia)
        {
            Type ColumnType = pi.PropertyType;
            if ((ColumnType.IsGenericType))
            {
                ColumnType = ColumnType.GetGenericArguments()[0];
            }
            dt.Columns.Add(pi.Name, ColumnType);
        }

        //Populate the data table
        foreach (T item in collection)
        {
            DataRow dr = dt.NewRow();
            dr.BeginEdit();
            foreach (PropertyInfo pi in pia)
            {
                if (pi.GetValue(item, null) != null)
                {
                    dr[pi.Name] = pi.GetValue(item, null);
                }
            }
            dr.EndEdit();
            dt.Rows.Add(dr);
        }
        return dt;
    }
 27
Author: CMS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-07 04:58:23

Poza dodatkowo używaniem Reflection do określania właściwości klasy Record do dbania o dodawanie nowych właściwości, to właściwie wszystko.

 1
Author: Mitch Wheat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-07 04:54:07

Sam napisałem małą bibliotekę, aby wykonać to zadanie. Używa odbicia tylko po raz pierwszy typ obiektu ma być przetłumaczony na datatable. Emituje metodę, która wykona całą pracę nad tłumaczeniem typu obiektu.

Its blazing fast. Znajdziesz go tutaj: ModelShredder na GoogleCode

 0
Author: Johannes Rudolph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-18 21:21:20

Wprowadziłem kilka zmian w metodzie rozszerzenia CMS, aby obsłużyć sprawę, gdy List zawiera elementy prymitywne lub String. W takim przypadku wynikowa DataTable będzie miała tylko jedną Column z Row dla każdej z wartości na liście.

Na początku myślałem o włączeniu wszystkich typów wartości (nie tylko prymitywnych), ale nie chciałem, aby struktury (które są typami wartości) były włączone.

Ta zmiana wynikła z mojej potrzeby przekształcenia List(Of Long), lub List<long>, w DataTable, aby użyć go jako Parametr wartości tabelarycznej w procedurze składowanej MS SQL 2008.

Przykro mi, że mój kod jest w VB, mimo że to pytanie jest oznaczone c # ; mój projekt jest w VB (nie mój wybór) i nie powinno być trudno zastosować zmiany w c#.

Imports System.Runtime.CompilerServices
Imports System.Reflection

Module Extensions

    <Extension()>
    Public Function ToDataTable(Of T)(ByVal collection As IEnumerable(Of T)) As DataTable
        Dim dt As DataTable = New DataTable("DataTable")
        Dim type As Type = GetType(T)
        Dim pia() As PropertyInfo = type.GetProperties()

        ' For a collection of primitive types create a 1 column DataTable
        If type.IsPrimitive OrElse type.Equals(GetType(String)) Then
            dt.Columns.Add("Column", type)
        Else
            ' Inspect the properties and create the column in the DataTable
            For Each pi As PropertyInfo In pia
                Dim ColumnType As Type = pi.PropertyType
                If ColumnType.IsGenericType Then
                    ColumnType = ColumnType.GetGenericArguments()(0)
                End If
                dt.Columns.Add(pi.Name, ColumnType)
            Next

        End If

        ' Populate the data table
        For Each item As T In collection
            Dim dr As DataRow = dt.NewRow()
            dr.BeginEdit()
            ' Set item as the value for the lone column on each row
            If type.IsPrimitive OrElse type.Equals(GetType(String)) Then
                dr("Column") = item
            Else
                For Each pi As PropertyInfo In pia
                    If pi.GetValue(item, Nothing) <> Nothing Then
                        dr(pi.Name) = pi.GetValue(item, Nothing)
                    End If
                Next
            End If
            dr.EndEdit()
            dt.Rows.Add(dr)
        Next
        Return dt
    End Function

End Module
 0
Author: Tlatoani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-31 02:57:33

Znalazłem ten kod na forum Microsoftu. Jest to do tej pory jeden z najprostszych sposobów, łatwy do zrozumienia i użycia. To zaoszczędziło mi godziny. Dostosowałem to jako metodę rozszerzenia bez żadnych zmian do rzeczywistej implementacji. Poniżej znajduje się kod. to nie wymaga wiele wyjaśnień.

Można używać dwóch podpisów funkcji z tą samą implementacją

1) public static DataSet ToDataSetFromObject (this object dsCollection)

2) publiczny statyczny zbiór danych Aby go zobaczyć, konieczne jest włączenie w przeglądarce obsługi JavaScript. Użyję tego w poniższym przykładzie.

// <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;
}

Aby użyć tego rozszerzenia w kodzie

Country[] objArrayCountry = null;
objArrayCountry = ....;// populate your array
if ((objArrayCountry != null)) {
    dataset = objArrayCountry.ToDataSetFromArrayOfObject();
}
 0
Author: kumar chandraketu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-01 16:58:12