将通用列表转换为C#中的数据集

时间:2009-08-07 16:12:42

标签: c# list dataset

我有一个通用的对象列表。每个对象有9个字符串属性。我想将该列表转换为可以传递给datagridview的数据集......最好的方法是什么?

10 个答案:

答案 0 :(得分:64)

我为回答这个问题而道歉,但我认为这是查看我的最终代码的最简单方法。它包含可空类型和空值的修复: - )

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

答案 1 :(得分:13)

您是否尝试过直接将列表绑定到datagridview?如果没有,请首先尝试,因为它会为您节省很多痛苦。如果您已经尝试过,请告诉我们出了什么问题,以便我们为您提供更好的建议。数据绑定根据数据对象实现的接口提供不同的行为。例如,如果您的数据对象仅实现IEnumerable(例如List),您将获得非常基本的单向绑定,但是如果它也实现了IBindingList(例如BindingList },DataView),然后你得到双向绑定。

答案 2 :(得分:12)

上面有Lee的扩展代码存在错误,您需要在迭代列表中的项目时将新填充的行添加到表格中。

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;

}

答案 3 :(得分:5)

您可以创建一个扩展方法,通过反射添加所有属性值:

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

答案 4 :(得分:3)

您可以查看

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

提供了一些不同的方法。

答案 5 :(得分:2)

强力代码回答你的问题:

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;

现在提出实际问题。你为什么想做这个?如前所述,您可以直接绑定到对象列表。也许一个仅采用数据集的报告工具?

答案 6 :(得分:2)

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

它是我所知道的最快的解决方案(这就是为什么我开发它:-))。您可以在此处找到它:GoogleCode上的ModelShredder

目前它只支持翻译到DataTable。当你提出问题时,这应该足够了。已经开发了对DataSet的支持(想想一个简单的反向ORM),当我从假期回来时,它将在两个弱点中发布: - )

答案 7 :(得分:1)

我通过处理值类型略微修改了接受的答案。我在尝试执行以下操作时遇到此问题,因为GetProperties()的值类型为零长度,我得到一个空数据集。我知道这不是OP的用例,但我想发布这个更改以防其他人遇到同样的事情。

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

答案 8 :(得分:0)

一种选择是使用System.ComponenetModel.BindingList而不是列表。

这允许您直接在DataGridView中使用它。与普通的System.Collections.Generic.List不同,它会在更改时更新DataGridView。

答案 9 :(得分:0)

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

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

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