在 C# 中将通用列表转换为数据集
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1245662/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert generic list to dataset in C#
提问by Goober
I have a Generic list of Objects. Each object has 9 string properties. I want to turn that list into a dataset that i can pass to a datagridview......Whats the best way to go about doing this?
我有一个通用的对象列表。每个对象有 9 个字符串属性。我想将该列表转换为可以传递给 datagridview 的数据集......这样做的最佳方法是什么?
采纳答案by Christian Hayter
Have you tried binding the list to the datagridview directly? If not, try that first because it will save you lots of pain. If you have tried it already, please tell us what went wrong so we can better advise you. Data binding gives you different behaviour depending on what interfaces your data object implements. For example, if your data object only implements IEnumerable
(e.g. List
), you will get very basic one-way binding, but if it implements IBindingList
as well (e.g. BindingList
, DataView
), then you get two-way binding.
您是否尝试过将列表直接绑定到 datagridview?如果没有,请先尝试,因为它会为您节省很多痛苦。如果您已经尝试过,请告诉我们出了什么问题,以便我们更好地为您提供建议。数据绑定根据数据对象实现的接口为您提供不同的行为。例如,如果您的数据对象仅实现IEnumerable
(例如List
),您将获得非常基本的单向绑定,但如果它也实现IBindingList
(例如BindingList
,DataView
),那么您将获得双向绑定。
回答by JDunkerley
One option would be to use a System.ComponenetModel.BindingList rather than a list.
一种选择是使用 System.ComponenetModel.BindingList 而不是列表。
This allows you to use it directly within a DataGridView. And unlike a normal System.Collections.Generic.List updates the DataGridView on changes.
这允许您直接在 DataGridView 中使用它。与普通的 System.Collections.Generic.List 不同的是,DataGridView 会在发生变化时更新。
回答by joshua.ewer
Brute force code to answer your question:
蛮力代码来回答你的问题:
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;
Now for the actual question. Why would you want to do this? As mentioned earlier, you can bind directly to an object list. Maybe a reporting tool that only takes datasets?
现在是实际问题。你为什么想做这个?如前所述,您可以直接绑定到对象列表。也许是一个只需要数据集的报告工具?
回答by Lee
You could create an extension method to add all property values through reflection:
您可以创建一个扩展方法来通过反射添加所有属性值:
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;
}
回答by Lee
There is a bug with Lee's extension code above, you need to add the newly filled row to the table t when iterating throught the items in the list.
上面 Lee 的扩展代码有一个错误,您需要在遍历列表中的项目时将新填充的行添加到表 t 中。
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;
}
}
回答by Bennett Dill
I apologize for putting an answer up to this question, but I figured it would be the easiest way to view my final code. It includes fixes for nullable types and null values :-)
我很抱歉回答这个问题,但我认为这将是查看我的最终代码的最简单方法。它包括可空类型和空值的修复:-)
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;
}
回答by Richard Edwards
I have slightly modified the accepted answer by handling value types. I came across this when trying to do the following and because GetProperties() is zero length for value types I was getting an empty dataset. I know this is not the use case for the OP but thought I'd post this change in case anyone else came across the same thing.
我通过处理值类型稍微修改了接受的答案。我在尝试执行以下操作时遇到了这个问题,并且因为 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;
}
回答by kumar chandraketu
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 it as extension method without any change to actual method. 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)
1) public static DataSet ToDataSetFromObject(这个对象dsCollection)
2) public static DataSet ToDataSetFromArrayOfObject( this object[] arrCollection) . I 'll be using this one for example.
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;
}
To use this extension in code
在代码中使用这个扩展
Country[] objArrayCountry = null;
objArrayCountry = ....;// populate your array
if ((objArrayCountry != null)) {
dataset = objArrayCountry.ToDataSetFromArrayOfObject();
}