如何将 List转换为 进入数据集?

发布于 2024-07-13 19:55:42 字数 1004 浏览 7 评论 0原文

给定一个对象列表,我需要将其转换为一个数据集,其中列表中的每个项目都由一行表示,每个属性都是该行中的一列。 然后,该数据集将被传递到 Aspose.Cells 函数用于创建 Excel 文档作为报告。

假设我有以下内容:

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

给定一个列表记录,如何将其转换为数据集,如下所示:

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

目前我唯一能想到的如下:

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

但是这种方式让我思考必须有更好的方法,因为在至少,如果将新属性添加到记录中,那么它们将不会显示在数据集中......但同时它允许我控制每个属性添加到行中的顺序。

有谁知道更好的方法来做到这一点?

Given a list of objects, I am needing to transform it into a dataset where each item in the list is represented by a row and each property is a column in the row. This DataSet will then be passed to an Aspose.Cells function in order to create an Excel document as a report.

Say I have the following:

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

Given a List records, how do I transform it into a DataSet as follows:

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

At the moment the only thing I can think of is as 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);
}

But this way leaves me thinking there must be a better way since at the very least if new properties are added to Record then they won't show up in the DataSet...but at the same time it allows me to control the order each property is added to the row.

Does anyone know of a better way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

丑疤怪 2024-07-20 19:55:42

您可以通过反射和泛型来完成此操作,检查基础类型的属性。

考虑我使用的扩展方法:

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

You can do it through reflection and generics, inspecting the properties of the underlying type.

Consider this extension method that I use:

    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;
    }
深居我梦 2024-07-20 19:55:42

我在微软论坛上找到了这段代码。 这是迄今为止最简单的方法之一,易于理解和使用。 这节省了我几个小时。 我已将其自定义为扩展方法,而不对实际实现进行任何更改。 下面是代码。 不需要太多解释。

您可以使用具有相同实现的两个函数签名

1) public static DataSet ToDataSetFromObject(this object dsCollection)

2) public static DataSet ToDataSetFromArrayOfObject( this object[] arrCollection)。 我将在下面的示例中使用这个。

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

在代码中使用此扩展

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

I found this code on Microsoft forum. This is so far one of easiest way, easy to understand and use. This has saved me hours. I have customized this as extension method without any change to actual implementaion. Below is the code. it doesn't require much explanation.

You can use two function signature with same implementation

1) public static DataSet ToDataSetFromObject(this object dsCollection)

2) public static DataSet ToDataSetFromArrayOfObject( this object[] arrCollection). I'll be using this one in below example.

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

To use this extension in code

Country[] objArrayCountry = null;
objArrayCountry = ....;// populate your array
if ((objArrayCountry != null)) {
    dataset = objArrayCountry.ToDataSetFromArrayOfObject();
}
暮光沉寂 2024-07-20 19:55:42

除了另外使用 Reflection 来确定类 Record 的属性以负责添加新属性之外,仅此而已。

Apart from additionally using Reflection to determine the properties of class Record to take care of adding new properties, that's pretty much it.

玻璃人 2024-07-20 19:55:42

我自己编写了一个小型库来完成这项任务。 它仅在第一次将对象类型转换为数据表时使用反射。 它发出一个方法来完成转换对象类型的所有工作。

速度极快。 您可以在此处找到它:GoogleCode 上的 ModelShredder

I've written a small library myself to accomplish this task. It uses reflection only for the first time an object type is to be translated to a datatable. It emits a method that will do all the work translating an object type.

Its blazing fast. You can find it here: ModelShredder on GoogleCode

烟柳画桥 2024-07-20 19:55:42

我对 CMS 的扩展方法进行了一些更改,以处理 List 包含原始元素或 String 元素的情况。 在这种情况下,生成的 DataTable 将只有一个 Column,其中列表中的每个值都有一个 Row

起初,我想到包含所有值类型(不仅仅是原始类型),但我不希望包含结构(即值类型)。

此更改源于我需要将 List(Of Long)List 转换为 DataTable 以将其用作MS SQL 2008 存储过程中的表值参数。

很抱歉,我的代码是用 VB 编写的,尽管这个问题被标记为

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

I made some changes to CMS' extension method to handle the case when the List contains primitive or String elements. In that case the resulting DataTable will only have one Column with a Row for each of the values in the list.

At first I thought of including all value types (not only primitive types) but I didn't want Structures (which are value types) to be included.

This change arose from my need of converting a List(Of Long), or List<long>, into a DataTable to use it as a Table-Valued Parameter in a MS SQL 2008 Stored Procedure.

I'm sorry my code is in VB even though this question is tagged ; my project is in VB (NOT my choice) and it shouldn't be hard to apply the changes in 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文