从这段代码我可以像我预期的那样调用bmwCars.CopyToDataTable().
var bmwCars = from car in dataTable.AsEnumerable() where car.Field("Make").ToLower().Equals("bmw") select car;
但是当我将一些代码声明更改为下面时,我无法调用CopyToDataTable(),为什么?
var bmwCars = from car in dataTable.AsEnumerable() where car.Field("Make").ToLower().Equals("bmw") select new { Make = car.Field ("Make"), Color = car.Field ("Color"), PetName = car.Field ("PetName") };
Tim Schmelte.. 7
您可以构建自己的CopyToDataTable,它接受任何类型的IEnumerable(不仅仅是DataRow
)并返回一个新的DataTable
:
// following would not compile by default // because input is not an IEnumerablebut an anonymous type var tblResult = bmwCars.CopyToDataTable();
这是实现(在MSDN的帮助下):
public class ObjectShredder{ private System.Reflection.FieldInfo[] _fi; private System.Reflection.PropertyInfo[] _pi; private System.Collections.Generic.Dictionary _ordinalMap; private System.Type _type; // ObjectShredder constructor. public ObjectShredder() { _type = typeof(T); _fi = _type.GetFields(); _pi = _type.GetProperties(); _ordinalMap = new Dictionary (); } /// /// Loads a DataTable from a sequence of objects. /// /// The sequence of objects to load into the DataTable. /// The input table. The schema of the table must match that /// the type T. If the table is null, a new table is created with a schema /// created from the public properties and fields of the type T. /// Specifies how values from the source sequence will be applied to /// existing rows in the table. ///A DataTable created from the source sequence. public DataTable Shred(IEnumerablesource, DataTable table, LoadOption? options) { // Load the table from the scalar sequence if T is a primitive type. if (typeof(T).IsPrimitive) { return ShredPrimitive(source, table, options); } // Create a new table if the input table is null. if (table == null) { table = new DataTable(typeof(T).Name); } // Initialize the ordinal map and extend the table schema based on type T. table = ExtendTable(table, typeof(T)); // Enumerate the source sequence and load the object values into rows. table.BeginLoadData(); using (IEnumerator e = source.GetEnumerator()) { while (e.MoveNext()) { if (options != null) { table.LoadDataRow(ShredObject(table, e.Current), (LoadOption)options); } else { table.LoadDataRow(ShredObject(table, e.Current), true); } } } table.EndLoadData(); // Return the table. return table; } public DataTable ShredPrimitive(IEnumerable source, DataTable table, LoadOption? options) { // Create a new table if the input table is null. if (table == null) { table = new DataTable(typeof(T).Name); } if (!table.Columns.Contains("Value")) { table.Columns.Add("Value", typeof(T)); } // Enumerate the source sequence and load the scalar values into rows. table.BeginLoadData(); using (IEnumerator e = source.GetEnumerator()) { Object[] values = new object[table.Columns.Count]; while (e.MoveNext()) { values[table.Columns["Value"].Ordinal] = e.Current; if (options != null) { table.LoadDataRow(values, (LoadOption)options); } else { table.LoadDataRow(values, true); } } } table.EndLoadData(); // Return the table. return table; } public object[] ShredObject(DataTable table, T instance) { FieldInfo[] fi = _fi; PropertyInfo[] pi = _pi; if (instance.GetType() != typeof(T)) { // If the instance is derived from T, extend the table schema // and get the properties and fields. ExtendTable(table, instance.GetType()); fi = instance.GetType().GetFields(); pi = instance.GetType().GetProperties(); } // Add the property and field values of the instance to an array. Object[] values = new object[table.Columns.Count]; foreach (FieldInfo f in fi) { values[_ordinalMap[f.Name]] = f.GetValue(instance); } foreach (PropertyInfo p in pi) { values[_ordinalMap[p.Name]] = p.GetValue(instance, null); } // Return the property and field values of the instance. return values; } public DataTable ExtendTable(DataTable table, Type type) { // Extend the table schema if the input table was null or if the value // in the sequence is derived from type T. foreach (FieldInfo f in type.GetFields()) { if (!_ordinalMap.ContainsKey(f.Name)) { // Add the field as a column in the table if it doesn't exist // already. DataColumn dc = table.Columns.Contains(f.Name) ? table.Columns[f.Name] : table.Columns.Add(f.Name, f.FieldType); // Add the field to the ordinal map. _ordinalMap.Add(f.Name, dc.Ordinal); } } foreach (PropertyInfo p in type.GetProperties()) { if (!_ordinalMap.ContainsKey(p.Name)) { // Add the property as a column in the table if it doesn't exist // already. DataColumn dc = table.Columns.Contains(p.Name) ? table.Columns[p.Name] : table.Columns.Add(p.Name, p.PropertyType); // Add the property to the ordinal map. _ordinalMap.Add(p.Name, dc.Ordinal); } } // Return the table. return table; } }
现在您可以添加以下扩展名:
public static class CustomLINQtoDataSetMethods { public static DataTable CopyToDataTable(this IEnumerable source) { return new ObjectShredder ().Shred(source, null, null); } public static DataTable CopyToDataTable (this IEnumerable source, DataTable table, LoadOption? options) { return new ObjectShredder ().Shred(source, table, options); } }
瞧!现在CopyToDataTable
适用于任何一种IEnumerable
:)
您可以构建自己的CopyToDataTable,它接受任何类型的IEnumerable(不仅仅是DataRow
)并返回一个新的DataTable
:
// following would not compile by default // because input is not an IEnumerablebut an anonymous type var tblResult = bmwCars.CopyToDataTable();
这是实现(在MSDN的帮助下):
public class ObjectShredder{ private System.Reflection.FieldInfo[] _fi; private System.Reflection.PropertyInfo[] _pi; private System.Collections.Generic.Dictionary _ordinalMap; private System.Type _type; // ObjectShredder constructor. public ObjectShredder() { _type = typeof(T); _fi = _type.GetFields(); _pi = _type.GetProperties(); _ordinalMap = new Dictionary (); } /// /// Loads a DataTable from a sequence of objects. /// /// The sequence of objects to load into the DataTable. /// The input table. The schema of the table must match that /// the type T. If the table is null, a new table is created with a schema /// created from the public properties and fields of the type T. /// Specifies how values from the source sequence will be applied to /// existing rows in the table. ///A DataTable created from the source sequence. public DataTable Shred(IEnumerablesource, DataTable table, LoadOption? options) { // Load the table from the scalar sequence if T is a primitive type. if (typeof(T).IsPrimitive) { return ShredPrimitive(source, table, options); } // Create a new table if the input table is null. if (table == null) { table = new DataTable(typeof(T).Name); } // Initialize the ordinal map and extend the table schema based on type T. table = ExtendTable(table, typeof(T)); // Enumerate the source sequence and load the object values into rows. table.BeginLoadData(); using (IEnumerator e = source.GetEnumerator()) { while (e.MoveNext()) { if (options != null) { table.LoadDataRow(ShredObject(table, e.Current), (LoadOption)options); } else { table.LoadDataRow(ShredObject(table, e.Current), true); } } } table.EndLoadData(); // Return the table. return table; } public DataTable ShredPrimitive(IEnumerable source, DataTable table, LoadOption? options) { // Create a new table if the input table is null. if (table == null) { table = new DataTable(typeof(T).Name); } if (!table.Columns.Contains("Value")) { table.Columns.Add("Value", typeof(T)); } // Enumerate the source sequence and load the scalar values into rows. table.BeginLoadData(); using (IEnumerator e = source.GetEnumerator()) { Object[] values = new object[table.Columns.Count]; while (e.MoveNext()) { values[table.Columns["Value"].Ordinal] = e.Current; if (options != null) { table.LoadDataRow(values, (LoadOption)options); } else { table.LoadDataRow(values, true); } } } table.EndLoadData(); // Return the table. return table; } public object[] ShredObject(DataTable table, T instance) { FieldInfo[] fi = _fi; PropertyInfo[] pi = _pi; if (instance.GetType() != typeof(T)) { // If the instance is derived from T, extend the table schema // and get the properties and fields. ExtendTable(table, instance.GetType()); fi = instance.GetType().GetFields(); pi = instance.GetType().GetProperties(); } // Add the property and field values of the instance to an array. Object[] values = new object[table.Columns.Count]; foreach (FieldInfo f in fi) { values[_ordinalMap[f.Name]] = f.GetValue(instance); } foreach (PropertyInfo p in pi) { values[_ordinalMap[p.Name]] = p.GetValue(instance, null); } // Return the property and field values of the instance. return values; } public DataTable ExtendTable(DataTable table, Type type) { // Extend the table schema if the input table was null or if the value // in the sequence is derived from type T. foreach (FieldInfo f in type.GetFields()) { if (!_ordinalMap.ContainsKey(f.Name)) { // Add the field as a column in the table if it doesn't exist // already. DataColumn dc = table.Columns.Contains(f.Name) ? table.Columns[f.Name] : table.Columns.Add(f.Name, f.FieldType); // Add the field to the ordinal map. _ordinalMap.Add(f.Name, dc.Ordinal); } } foreach (PropertyInfo p in type.GetProperties()) { if (!_ordinalMap.ContainsKey(p.Name)) { // Add the property as a column in the table if it doesn't exist // already. DataColumn dc = table.Columns.Contains(p.Name) ? table.Columns[p.Name] : table.Columns.Add(p.Name, p.PropertyType); // Add the property to the ordinal map. _ordinalMap.Add(p.Name, dc.Ordinal); } } // Return the table. return table; } }
现在您可以添加以下扩展名:
public static class CustomLINQtoDataSetMethods { public static DataTable CopyToDataTable(this IEnumerable source) { return new ObjectShredder ().Shred(source, null, null); } public static DataTable CopyToDataTable (this IEnumerable source, DataTable table, LoadOption? options) { return new ObjectShredder ().Shred(source, table, options); } }
瞧!现在CopyToDataTable
适用于任何一种IEnumerable
:)
根据您的使用情况Field
,dataTable
(我假设的类型Car
)对象继承DataRow
.这是调用CopyToDataTable
扩展方法所必需的.但是,如上所述,您将返回无法继承的匿名类型的枚举DataRow
.
所以,可能是你的
select new
应该
select new Car
这样你就可以返回一个匿名类型IEnumerable
而不是一个IEnumerable<>
匿名类型.
根据Car
类的确切结构,可能需要进行一些次要的语法更改.如果Car
有公共属性,Make
,Color
,和PetName
那么它会工作,我建议.相反,如果Car
有一个方法签名大约等于的构造函数
public Car(string make, string color, string petName)
那么你将不得不改变LINQ语句
var bmwCars = from car in dataTable.AsEnumerable() where car.Field("Make").ToLower().Equals.("bmw") select new Car( car.Field ("Make"), car.Field ("Color"), car.Field ("PetName") );