如何将DataTable转换为动态对象?

如何在IEnumerable转换DataTable

例如,我想转换任何 DataTable

 ID | Name DI | emaN --------- or --------- 1 | x 2 | x 2 | y 1 | y 

在对象列表中

 // list 1 (ex 1) // list 2 (ex 2) { { { ID = 1, Name = "x" } { DI = 2, emaN = "x" } { ID = 2, Name = "y" } { DI = 1, emaN = "y" } } } 

所以

 list1.First().ID // 1 list2.First().emaN // "x" 

我该怎么做?

使用DynamicObject怎么样:

 public static class DataTableX { public static IEnumerable AsDynamicEnumerable(this DataTable table) { // Validate argument here.. return table.AsEnumerable().Select(row => new DynamicRow(row)); } private sealed class DynamicRow : DynamicObject { private readonly DataRow _row; internal DynamicRow(DataRow row) { _row = row; } // Interprets a member-access as an indexer-access on the // contained DataRow. public override bool TryGetMember(GetMemberBinder binder, out object result) { var retVal = _row.Table.Columns.Contains(binder.Name); result = retVal ? _row[binder.Name] : null; return retVal; } } } 

如果您希望使动态行可写,您还可以尝试重写TrySetMember

用法

  DataTable table = ... var dynamicTable = table.AsDynamicEnumerable(); var firstRowsNameField = dynamicTable.First().Name; 
 class Program { static void Main() { var dt = new DataTable(); dt.Columns.Add("ID", typeof(int)); dt.Columns.Add("Name", typeof(string)); dt.Rows.Add(1, "x"); dt.Rows.Add(2, "y"); List dynamicDt = dt.ToDynamic(); Console.WriteLine(dynamicDt.First().ID); Console.WriteLine(dynamicDt.First().Name); } } public static class DataTableExtensions { public static List ToDynamic(this DataTable dt) { var dynamicDt = new List(); foreach (DataRow row in dt.Rows) { dynamic dyn = new ExpandoObject(); dynamicDt.Add(dyn); foreach (DataColumn column in dt.Columns) { var dic = (IDictionary)dyn; dic[column.ColumnName] = row[column]; } } return dynamicDt; } } 

以前的suneelsarraf代码仅生成运行时动态对象,其属性为字符串。 以下更新将根据DataTable列的数据类型生成每个属性。

 public static class DataTableExtension { ///  /// Convert a database data table to a runtime dynamic definied type collection (dynamic class' name as table name). ///  ///  ///  ///  public static List ToDynamicList(DataTable dt, string className) { return ToDynamicList(ToDictionary(dt), getNewObject(dt.Columns, className)); } private static List> ToDictionary(DataTable dt) { var columns = dt.Columns.Cast(); var Temp = dt.AsEnumerable().Select(dataRow => columns.Select(column => new { Column = column.ColumnName, Value = dataRow[column] }) .ToDictionary(data => data.Column, data => data.Value)).ToList(); return Temp.ToList(); } private static List ToDynamicList(List> list, Type TypeObj) { dynamic temp = new List(); foreach (Dictionary step in list) { object Obj = Activator.CreateInstance(TypeObj); PropertyInfo[] properties = Obj.GetType().GetProperties(); Dictionary DictList = (Dictionary)step; foreach (KeyValuePair keyValuePair in DictList) { foreach (PropertyInfo property in properties) { if (property.Name == keyValuePair.Key) { if (keyValuePair.Value != null && keyValuePair.Value.GetType() != typeof(System.DBNull)) { if (keyValuePair.Value.GetType() == typeof(System.Guid)) { property.SetValue(Obj, keyValuePair.Value, null); } else { property.SetValue(Obj, keyValuePair.Value, null); } } break; } } } temp.Add(Obj); } return temp; } private static Type getNewObject(DataColumnCollection columns, string className) { AssemblyName assemblyName = new AssemblyName(); assemblyName.Name = "YourAssembly"; System.Reflection.Emit.AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); ModuleBuilder module = assemblyBuilder.DefineDynamicModule("YourDynamicModule"); TypeBuilder typeBuilder = module.DefineType(className, TypeAttributes.Public); foreach (DataColumn column in columns) { string propertyName = column.ColumnName; FieldBuilder field = typeBuilder.DefineField(propertyName, column.DataType, FieldAttributes.Public); PropertyBuilder property = typeBuilder.DefineProperty(propertyName, System.Reflection.PropertyAttributes.None, column.DataType, new Type[] { column.DataType }); MethodAttributes GetSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig; MethodBuilder currGetPropMthdBldr = typeBuilder.DefineMethod("get_value", GetSetAttr, column.DataType, new Type[] { column.DataType }); // Type.EmptyTypes); ILGenerator currGetIL = currGetPropMthdBldr.GetILGenerator(); currGetIL.Emit(OpCodes.Ldarg_0); currGetIL.Emit(OpCodes.Ldfld, field); currGetIL.Emit(OpCodes.Ret); MethodBuilder currSetPropMthdBldr = typeBuilder.DefineMethod("set_value", GetSetAttr, null, new Type[] { column.DataType }); ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator(); currSetIL.Emit(OpCodes.Ldarg_0); currSetIL.Emit(OpCodes.Ldarg_1); currSetIL.Emit(OpCodes.Stfld, field); currSetIL.Emit(OpCodes.Ret); property.SetGetMethod(currGetPropMthdBldr); property.SetSetMethod(currSetPropMthdBldr); } Type obj = typeBuilder.CreateType(); return obj; } } 

有些ORM可以直接从DB读取到dynamic ExpandoObject 。 例如petapoco (在这里阅读示例 )

或者你可以尝试类似的东西:

 var dt = new DataTable(); var dns = new List(); foreach (var item in dt.AsEnumerable()) { // Expando objects are IDictionary IDictionary dn = new ExpandoObject(); foreach (var column in dt.Columns.Cast()) { dn[column.ColumnName] = item[column]; } dns.Add(dn); } // Now you can do something like dns[0].MyColumnName // or recast to IDictionary and do // something like casted["MyColumnName"] 

尝试

 var MyResult = from x in MyDataTable select new { ID = x["ID"], Name = x["Name"] }.ToList (); 

将数据表转换为列表

  #region "Convert DataTable to List" public List ToDynamicList(DataTable dt) { List cols = (dt.Columns.Cast()).Select(column => column.ColumnName).ToList(); return ToDynamicList(ToDictionary(dt), getNewObject(cols)); } public List> ToDictionary(DataTable dt) { var columns = dt.Columns.Cast(); var Temp = dt.AsEnumerable().Select(dataRow => columns.Select(column => new { Column = column.ColumnName, Value = dataRow[column] }) .ToDictionary(data => data.Column, data => data.Value)).ToList(); return Temp.ToList(); } public List ToDynamicList(List> list, Type TypeObj) { dynamic temp = new List(); foreach (Dictionary step in list) { object Obj = Activator.CreateInstance(TypeObj); PropertyInfo[] properties = Obj.GetType().GetProperties(); Dictionary DictList = (Dictionary)step; foreach (KeyValuePair keyValuePair in DictList) { foreach (PropertyInfo property in properties) { if (property.Name == keyValuePair.Key) { property.SetValue(Obj, keyValuePair.Value.ToString(), null); break; } } } temp.Add(Obj); } return temp; } private Type getNewObject(List list) { AssemblyName assemblyName = new AssemblyName(); assemblyName.Name = "tmpAssembly"; AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); ModuleBuilder module = assemblyBuilder.DefineDynamicModule("tmpModule"); TypeBuilder typeBuilder = module.DefineType("WebgridRowCellCollection", TypeAttributes.Public); foreach (string step in list) { string propertyName = step; FieldBuilder field = typeBuilder.DefineField(propertyName, typeof(string), FieldAttributes.Public); PropertyBuilder property = typeBuilder.DefineProperty(propertyName, System.Reflection.PropertyAttributes.None, typeof(string), new Type[] { typeof(string) }); MethodAttributes GetSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig; MethodBuilder currGetPropMthdBldr = typeBuilder.DefineMethod("get_value", GetSetAttr, typeof(string), Type.EmptyTypes); ILGenerator currGetIL = currGetPropMthdBldr.GetILGenerator(); currGetIL.Emit(OpCodes.Ldarg_0); currGetIL.Emit(OpCodes.Ldfld, field); currGetIL.Emit(OpCodes.Ret); MethodBuilder currSetPropMthdBldr = typeBuilder.DefineMethod("set_value", GetSetAttr, null, new Type[] { typeof(string) }); ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator(); currSetIL.Emit(OpCodes.Ldarg_0); currSetIL.Emit(OpCodes.Ldarg_1); currSetIL.Emit(OpCodes.Stfld, field); currSetIL.Emit(OpCodes.Ret); property.SetGetMethod(currGetPropMthdBldr); property.SetSetMethod(currSetPropMthdBldr); } Type obj = typeBuilder.CreateType(); return obj; } #endregion 

你可以使用这样的扩展:

 using System; using System.Collections.Generic; using System.Data; using System.Dynamic; public static class DataTableExtensions { public static IEnumerable AsDynamicEnumerable(this DataTable table) { if (table == null) { yield break; } foreach (DataRow row in table.Rows) { IDictionary dRow = new ExpandoObject(); foreach (DataColumn column in table.Columns) { var value = row[column.ColumnName]; dRow[column.ColumnName] = Convert.IsDBNull(value) ? null : value; } yield return dRow; } } } 

用法:

 var dataTable = GetDataTableFromSomewhere(); var dynamicTable = dataTable.AsDynamicEnumerable(); var firstRowIDColumn = dynamicTable.First().ID; var lastRowIDColumn = dynamicTable.Last()["ID"]; 

但如果可能的话,我更喜欢IDataReader方法。