C# 将 DataRow 转换为对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1709596/
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 DataRow to object
提问by arek
I've created generic List and populate with some objects. Then List I mentioned before converted into DataTable to use in DataGridView. Problem is when I want get Row from this grid I have DataRow. I wanted to convert this to my object againt but not sure how to do it. Maybe you could give some example?
我创建了通用列表并填充了一些对象。然后我之前提到的List转换成DataTable在DataGridView中使用。问题是当我想从这个网格中获取 Row 时,我有 DataRow。我想再次将其转换为我的对象,但不知道该怎么做。也许你可以举一些例子?
Thanks
谢谢
回答by Thomas Levesque
Assuming you're using a class MyObject
, defined as follows :
假设您使用的是 class MyObject
,定义如下:
class MyObject
{
public string Foo { get; set; }
public int Foo { get; set; }
}
You could do something like that :
你可以这样做:
using System.Data.DataSetExtensions;
...
List<MyObject> list = (from row in table.AsEnumerable()
select new MyObject
{
Foo = row.Field<string>("foo"),
Bar = row.Field<int>("bar")
}).ToList();
回答by marc_s
Well, if you can't or won't use an "ORM" (object-relational mapper, like Linq-to-SQL or NHibernate - that's exactly what these tools do, and do quite well for you), you'll have to do this yourself.
好吧,如果您不能或不会使用“ORM”(对象关系映射器,如 Linq-to-SQL 或 NHibernate - 这正是这些工具所做的,并且为您做得很好),您将拥有自己做。
Converting a DataRow into a domain object model is pretty boring code, really:
将 DataRow 转换为域对象模型是非常无聊的代码,真的:
public Customer ConvertRowToCustomer(DataRow row)
{
Customer result = new Customer();
result.ID = row.Field<int>("ID");
result.Name = row.Field<string>("CustomerName");
..... // and so on
return result;
}
The biggest challenge here is making this rock-solid and handling (or avoiding) all possible errors (like a field being NULL etc.).
这里最大的挑战是使这个坚如磐石并处理(或避免)所有可能的错误(如字段为 NULL 等)。
Another possibility would be to have a constructor on your domain model object type that would take a DataRow
as parameter and construct a new object from it.
另一种可能性是在域模型对象类型上有一个构造函数,它将 aDataRow
作为参数并从中构造一个新对象。
Marc
马克
回答by Zack
Why not just put your objects into a BindingList<> rather than a List<>? Then you can skip the converting to DataTable and back again exercise. You may need to implement INotifyPropertyChangedon your objects, but once they are inside a BindingList, changes in the datagrid will automatically be applied to your underlying objects.
为什么不直接将对象放入 BindingList<> 而不是 List<> 中?然后您可以跳过转换为 DataTable 并再次返回练习。您可能需要在您的对象上实现INotifyPropertyChanged,但是一旦它们位于 BindingList 中,数据网格中的更改将自动应用于您的底层对象。
Sorting can be handled by either sorting the list manually on column header click, or by inheriting from BindingList<> and implementing the sorting functionality inside it - then clicking on a header automatically sorts the list - no code required.
排序可以通过在单击列标题时手动对列表进行排序来处理,也可以通过从 BindingList<> 继承并在其中实现排序功能来处理 - 然后单击标题自动对列表进行排序 - 无需代码。
回答by YeinCM-Qva
Well nowadays it is easier using ORMs of course. But if still you're using the old fashion you can go with a pretty easy Extension Class to do the job for you using a little bit of reflection and generic methods and lambda as follows:
现在当然使用 ORM 更容易。但是如果你仍然使用旧的方式,你可以使用一个非常简单的扩展类来为你完成这项工作,使用一些反射和泛型方法以及 lambda,如下所示:
public static class MapperExtensionClass
{
public static IEnumerable<MyClassType> ToMyClassTypeEnumerable(this DataTable table)
{
return table.AsEnumerable().Select(r => r.ToMyClassType());
}
public static MyClassType ToMyClassType(this DataRow row)
{
return row.ToObject<MyClassType>();
}
public static T ToObject<T>(this DataRow row) where T: new()
{
T obj = new T();
foreach (PropertyInfo property in typeof(T).GetProperties())
{
if (row.Table.Columns.Contains(property.Name))
{
property.SetValue(obj, property.PropertyType.ToDefault(row[property.Name]));
}
}
return obj;
}
public static object ToDefault(this Type type, object obj)
{
if (type == null)
throw new Exception("Customized exception message");
var method = typeof(MapperExtensionClass)
.GetMethod("ToDefaultGeneric", BindingFlags.Static | BindingFlags.Public);
var generic = method.MakeGenericMethod(type);
return generic.Invoke(null, new object[] { obj });
}
public static T ToDefaultGeneric<T>(object obj)
{
if (obj == null || obj == DBNull.Value)
{
return default(T);
}
else
{
return (T)obj;
}
}
}
You should also remember GridView objects can bind a lot of data source types. So it is your decision from a design point about what you should go with.
您还应该记住 GridView 对象可以绑定很多数据源类型。因此,您应该从设计角度决定应该采用什么。