简体   繁体   English

将DataRow转换为对象

[英]Convert DataRow to object

I've created generic List and populate with some objects. 我已经创建了通用List并填充了一些对象。 Then List I mentioned before converted into DataTable to use in DataGridView. 然后我在前面提到的List转换为DataTable以在DataGridView中使用。 Problem is when I want get Row from this grid I have DataRow. 问题是,当我想从这个网格获取Row时,我有DataRow。 I wanted to convert this to my object againt but not sure how to do it. 我想把它转换成我的对象,但不知道该怎么做。 Maybe you could give some example? 也许你可以举一些例子?

Thanks 谢谢

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. 另一种可能性是在域模型对象类型上有一个构造函数,它将DataRow作为参数并从中构造一个新对象。

Marc

Assuming you're using a class MyObject , defined as follows : 假设您使用的是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();

Why not just put your objects into a BindingList<> rather than a List<>? 为什么不将对象放入BindingList <>而不是List <>? Then you can skip the converting to DataTable and back again exercise. 然后,您可以跳过转换为DataTable并再次返回练习。 You may need to implement INotifyPropertyChanged on your objects, but once they are inside a BindingList, changes in the datagrid will automatically be applied to your underlying objects. 您可能需要在对象上实现INotifyPropertyChanged ,但是一旦它们位于BindingList中,datagrid中的更改将自动应用于您的基础对象。

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 <>并在其中实现排序功能来处理排序 - 然后单击标题会自动对列表进行排序 - 无需代码。

Well nowadays it is easier using ORMs of course. 那么现在使用ORM更容易。 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: 但是,如果你仍然使用旧时尚,你可以使用一个非常简单的扩展类来为你完成这项工作,使用一些反射和泛型方法和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. 您还应该记住GridView对象可以绑定很多数据源类型。 So it is your decision from a design point about what you should go with. 所以从设计角度决定你应该选择什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM