如何将List 转换为DataSet?

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

说我有以下内容:

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

给定List记录,如何将其转换为DataSet,如下所示:

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

但这种方式让我觉得必须有一个更好的方法,因为至少如果将新属性添加到R​​ecord,那么它们将不会显示在DataSet中……但同时它允许我控制每个属性被添加到行中。

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

您可以通过reflection和generics来检查基础类型的属性。

考虑我使用的这种扩展方法:

  public static DataTable ToDataTable(this IEnumerable 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; } 

除了另外使用Reflection来确定类Record的属性以处理添加新属性之外,这几乎就是它。

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

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

1)public static DataSet ToDataSetFromObject(此对象为 dsCollection)

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

 //  // Serialize Object to XML and then read it into a DataSet: //  // Array of object // dataset 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(); } 

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

它的速度非常快。 你可以在这里找到它: GoogleCode上的ModelShredder

我对CMS的扩展方法进行了一些更改,以便在List包含基元或String元素时处理这种情况。 在这种情况下,结果DataTable只有一个ColumnRow中的每个值都有一行。

起初我想到包括所有值类型(不仅是原始类型),但我不想要包含Structures(它们是值类型)。

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

对不起,我的代码在VB中,即使这个问题被标记为c# ; 我的项目是VB(不是我的选择),应用c#中的更改应该不难。

 Imports System.Runtime.CompilerServices Imports System.Reflection Module Extensions  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