将DataRow转换为对象

时间:2009-11-10 17:12:56

标签: c# .net

我创建了通用List并填充了一些对象。然后我在前面提到的List转换为DataTable以在DataGridView中使用。问题是,当我想从这个网格获取Row时,我有DataRow。我想把它转换成我的对象,但不知道该怎么做。也许你可以举一些例子?

由于

4 个答案:

答案 0 :(得分:11)

好吧,如果您不能或不会使用“ORM”(对象关系映射器,如Linq-to-SQL或NHibernate - 这正是这些工具所做的,并为您做得很好),我必须自己做。

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

这里最大的挑战是使这个坚如磐石并处理(或避免)所有可能的错误(如字段为NULL等)。

另一种可能性是在域模型对象类型上有一个构造函数,它将DataRow作为参数并从中构造一个新对象。

马克

答案 1 :(得分:8)

假设您正在使用类MyObject,定义如下:

class MyObject
{
    public string Foo { get; set; }
    public int Foo { get; set; }
}

你可以这样做:

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

答案 2 :(得分:1)

为什么不将对象放入BindingList&lt;&gt;而不是List&lt;&gt;?然后,您可以跳过转换为DataTable并再次返回练习。您可能需要在对象上实现 INotifyPropertyChanged ,但一旦它们位于BindingList中,datagrid中的更改将自动应用于您的基础对象。

可以通过在列标题单击上手动排序列表,或通过继承BindingList&lt;&gt;来处理排序。并在其中实现排序功能 - 然后单击标题会自动对列表进行排序 - 无需代码。

答案 3 :(得分:0)

现在使用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;
            }
        }
}

您还应该记住GridView对象可以绑定很多数据源类型。所以从设计角度决定你应该采用什么。