如何将 LINQ ToList() 函数转换为数据表 c#
How to convert LINQ ToList() function to datatable c#
这就是我的 xml 的样子
<?xml version="1.0" encoding="utf-8"?>
<Root>
<orders>
<OrderID>10248</OrderID>
<CustomerID>VINET</CustomerID>
<EmployeeID>5</EmployeeID>
<OrderDate>1996-07-04T00:00:00</OrderDate>
<RequiredDate>1996-08-01T00:00:00</RequiredDate>
<ShippedDate>1996-07-16T00:00:00</ShippedDate>
<ShipVia>3</ShipVia>
<Freight>32.3800</Freight>
<ShipName>Vins et alcools Chevalier</ShipName>
<ShipAddress>59 rue de l'Abbaye</ShipAddress>
<ShipCity>Reims</ShipCity>
<ShipPostalCode>51100</ShipPostalCode>
<ShipCountry>France</ShipCountry>
</orders>
</Root>
我用这种方式使用 LINQ 解析上面的 xml
document.Descendants("orders").Select(c => c).ToList()
我想以表格格式列出 xml 数据,就像 sql 查询 return 数据一样。
我搜索并得到 link link 建议使用我遵循的 CopyToDataTable() extension
方法,但我仍然没有得到表格格式的结果。
所以指导我如何转换我的 ToList() to Datatable
结果输出看起来像
OrderID CustomerID EmployeeID
------- ---------- -----------
10248 VINET 5
10249 AJAY 11
11027 Smith 09
这是我从 MSDN 获得的 CopyToDataTable 的完整代码
public static class DataSetLinqOperators
{
public static DataTable CopyToDataTable<T>(this IEnumerable<T> source)
{
return new ObjectShredder<T>().Shred(source, null, null);
}
public static DataTable CopyToDataTable<T>(this IEnumerable<T> source,
DataTable table, LoadOption? options)
{
return new ObjectShredder<T>().Shred(source, table, options);
}
}
public class ObjectShredder<T>
{
private FieldInfo[] _fi;
private PropertyInfo[] _pi;
private Dictionary<string, int> _ordinalMap;
private Type _type;
public ObjectShredder()
{
_type = typeof(T);
_fi = _type.GetFields();
_pi = _type.GetProperties();
_ordinalMap = new Dictionary<string, int>();
}
public DataTable Shred(IEnumerable<T> source, DataTable table, LoadOption? options)
{
if (typeof(T).IsPrimitive)
{
return ShredPrimitive(source, table, options);
}
if (table == null)
{
table = new DataTable(typeof(T).Name);
}
// now see if need to extend datatable base on the type T + build ordinal map
table = ExtendTable(table, typeof(T));
table.BeginLoadData();
using (IEnumerator<T> 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 table;
}
public DataTable ShredPrimitive(IEnumerable<T> source, DataTable table, LoadOption? options)
{
if (table == null)
{
table = new DataTable(typeof(T).Name);
}
if (!table.Columns.Contains("Value"))
{
table.Columns.Add("Value", typeof(T));
}
table.BeginLoadData();
using (IEnumerator<T> 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 table;
}
public DataTable ExtendTable(DataTable table, Type type)
{
// value is type derived from T, may need to extend table.
foreach (FieldInfo f in type.GetFields())
{
if (!_ordinalMap.ContainsKey(f.Name))
{
DataColumn dc = table.Columns.Contains(f.Name) ? table.Columns[f.Name]
: table.Columns.Add(f.Name, f.FieldType);
_ordinalMap.Add(f.Name, dc.Ordinal);
}
}
foreach (PropertyInfo p in type.GetProperties())
{
if (!_ordinalMap.ContainsKey(p.Name))
{
DataColumn dc = table.Columns.Contains(p.Name) ? table.Columns[p.Name]
: table.Columns.Add(p.Name, p.PropertyType);
_ordinalMap.Add(p.Name, dc.Ordinal);
}
}
return table;
}
public object[] ShredObject(DataTable table, T instance)
{
FieldInfo[] fi = _fi;
PropertyInfo[] pi = _pi;
if (instance.GetType() != typeof(T))
{
ExtendTable(table, instance.GetType());
fi = instance.GetType().GetFields();
pi = instance.GetType().GetProperties();
}
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 values;
}
}
然后以这种方式调用 DataTable dtt =document.Descendants("orders").Select(c => c).ToList().CopyToDataTable();
但它没有按照我想要的输出方式工作。
使用readxml将xml转换为数据表。下面的腿,值是 IEnumerable
类型
IEnumerable<XElement> values =
from el in root.Elements("orders")
select el;
DataSet ds = new DataSet();
ds.ReadXml(new StringReader(new XElement("Root", values).ToString()));
DataTable d = ds.Tables[0];
dgv.DataSource = d; // dgv is a Data Grid View
Microsoft 发布了一个示例 class,它运行起来非常可靠且快速(就 而言,速度与基于反射的解决方案一样快)。
它叫做 ObjectShredder
,你可以从 msdn
中获取它
使用此 ExtensionMethod 效果最佳
public static class CustomLINQtoDataSetMethods
{
public static DataTable CopyToDataTable<T>(this IEnumerable<T> source)
{
return new ObjectShredder<T>().Shred(source, null, null);
}
public static DataTable CopyToDataTable<T>(
this IEnumerable<T> source, DataTable table, LoadOption? options)
{
return new ObjectShredder<T>().Shred(source, table, options);
}
}
但是由于 document.Descendants("orders")
returns XElement
类型没有有用的属性但有一些 XElements 我建议您改用匿名类型。
用法:
var query = from o in document.Descendants("orders")
select new
{
OrderID = (int)o.Element("OrderID"),
CustomerID = (string)o.Element("CustomerID"),
EmployeeID = (int)o.Element("EmployeeID"),
};
var table = query.ToDataTable();
我还不能添加评论,所以你可以在这里做什么
根据下面的回答thread
您需要参考 FastMember
public static DataTable ToDataTable<T>(this IEnumerable<T> data)
{
if (data == null)
throw new ArgumentNullException("data");
var table = new DataTable("sd");
using (var reader = ObjectReader.Create(data))
{
table.Load(reader);
}
return table;
}
如果您使用的是 DataContext (linq-to-sql)
public static DataTable ToDataTable<T>(this IQueryable<T> query, DataContext context)
{
if (query == null)
{
throw new ArgumentNullException("query");
}
IDbCommand cmd = context.GetCommand(query.AsQueryable());
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = (SqlCommand)cmd;
DataTable dt = new DataTable("sd");
try
{
cmd.Connection.Open();
adapter.FillSchema(dt, SchemaType.Source);
adapter.Fill(dt);
}
finally
{
cmd.Connection.Close();
}
return dt;
}
已更新
你可以使用下面的功能
public static DataTable ConvertToDataTable(IEnumerable<XElement> data)
{
var table = new DataTable();
// create the columns
foreach(var xe in data.First().Descendants())
table.Columns.Add(xe.Name.LocalName,typeof(string));
// fill the data
foreach(var item in data)
{
var row = table.NewRow();
foreach(var xe in item.Descendants())
row[xe.Name.LocalName] = xe.Value;
table.Rows.Add(row);
}
return table;
}
并使用函数
var table = ConvertToDataTable(document.Descendants("orders"));
在这里工作sample
这就是我的 xml 的样子
<?xml version="1.0" encoding="utf-8"?>
<Root>
<orders>
<OrderID>10248</OrderID>
<CustomerID>VINET</CustomerID>
<EmployeeID>5</EmployeeID>
<OrderDate>1996-07-04T00:00:00</OrderDate>
<RequiredDate>1996-08-01T00:00:00</RequiredDate>
<ShippedDate>1996-07-16T00:00:00</ShippedDate>
<ShipVia>3</ShipVia>
<Freight>32.3800</Freight>
<ShipName>Vins et alcools Chevalier</ShipName>
<ShipAddress>59 rue de l'Abbaye</ShipAddress>
<ShipCity>Reims</ShipCity>
<ShipPostalCode>51100</ShipPostalCode>
<ShipCountry>France</ShipCountry>
</orders>
</Root>
我用这种方式使用 LINQ 解析上面的 xml
document.Descendants("orders").Select(c => c).ToList()
我想以表格格式列出 xml 数据,就像 sql 查询 return 数据一样。
我搜索并得到 link link 建议使用我遵循的
CopyToDataTable() extension
方法,但我仍然没有得到表格格式的结果。
所以指导我如何转换我的 ToList() to Datatable
结果输出看起来像
OrderID CustomerID EmployeeID
------- ---------- -----------
10248 VINET 5
10249 AJAY 11
11027 Smith 09
这是我从 MSDN 获得的 CopyToDataTable 的完整代码
public static class DataSetLinqOperators
{
public static DataTable CopyToDataTable<T>(this IEnumerable<T> source)
{
return new ObjectShredder<T>().Shred(source, null, null);
}
public static DataTable CopyToDataTable<T>(this IEnumerable<T> source,
DataTable table, LoadOption? options)
{
return new ObjectShredder<T>().Shred(source, table, options);
}
}
public class ObjectShredder<T>
{
private FieldInfo[] _fi;
private PropertyInfo[] _pi;
private Dictionary<string, int> _ordinalMap;
private Type _type;
public ObjectShredder()
{
_type = typeof(T);
_fi = _type.GetFields();
_pi = _type.GetProperties();
_ordinalMap = new Dictionary<string, int>();
}
public DataTable Shred(IEnumerable<T> source, DataTable table, LoadOption? options)
{
if (typeof(T).IsPrimitive)
{
return ShredPrimitive(source, table, options);
}
if (table == null)
{
table = new DataTable(typeof(T).Name);
}
// now see if need to extend datatable base on the type T + build ordinal map
table = ExtendTable(table, typeof(T));
table.BeginLoadData();
using (IEnumerator<T> 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 table;
}
public DataTable ShredPrimitive(IEnumerable<T> source, DataTable table, LoadOption? options)
{
if (table == null)
{
table = new DataTable(typeof(T).Name);
}
if (!table.Columns.Contains("Value"))
{
table.Columns.Add("Value", typeof(T));
}
table.BeginLoadData();
using (IEnumerator<T> 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 table;
}
public DataTable ExtendTable(DataTable table, Type type)
{
// value is type derived from T, may need to extend table.
foreach (FieldInfo f in type.GetFields())
{
if (!_ordinalMap.ContainsKey(f.Name))
{
DataColumn dc = table.Columns.Contains(f.Name) ? table.Columns[f.Name]
: table.Columns.Add(f.Name, f.FieldType);
_ordinalMap.Add(f.Name, dc.Ordinal);
}
}
foreach (PropertyInfo p in type.GetProperties())
{
if (!_ordinalMap.ContainsKey(p.Name))
{
DataColumn dc = table.Columns.Contains(p.Name) ? table.Columns[p.Name]
: table.Columns.Add(p.Name, p.PropertyType);
_ordinalMap.Add(p.Name, dc.Ordinal);
}
}
return table;
}
public object[] ShredObject(DataTable table, T instance)
{
FieldInfo[] fi = _fi;
PropertyInfo[] pi = _pi;
if (instance.GetType() != typeof(T))
{
ExtendTable(table, instance.GetType());
fi = instance.GetType().GetFields();
pi = instance.GetType().GetProperties();
}
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 values;
}
}
然后以这种方式调用 DataTable dtt =document.Descendants("orders").Select(c => c).ToList().CopyToDataTable();
但它没有按照我想要的输出方式工作。
使用readxml将xml转换为数据表。下面的腿,值是 IEnumerable
类型 IEnumerable<XElement> values =
from el in root.Elements("orders")
select el;
DataSet ds = new DataSet();
ds.ReadXml(new StringReader(new XElement("Root", values).ToString()));
DataTable d = ds.Tables[0];
dgv.DataSource = d; // dgv is a Data Grid View
Microsoft 发布了一个示例 class,它运行起来非常可靠且快速(就 而言,速度与基于反射的解决方案一样快)。
它叫做 ObjectShredder
,你可以从 msdn
使用此 ExtensionMethod 效果最佳
public static class CustomLINQtoDataSetMethods
{
public static DataTable CopyToDataTable<T>(this IEnumerable<T> source)
{
return new ObjectShredder<T>().Shred(source, null, null);
}
public static DataTable CopyToDataTable<T>(
this IEnumerable<T> source, DataTable table, LoadOption? options)
{
return new ObjectShredder<T>().Shred(source, table, options);
}
}
但是由于 document.Descendants("orders")
returns XElement
类型没有有用的属性但有一些 XElements 我建议您改用匿名类型。
用法:
var query = from o in document.Descendants("orders")
select new
{
OrderID = (int)o.Element("OrderID"),
CustomerID = (string)o.Element("CustomerID"),
EmployeeID = (int)o.Element("EmployeeID"),
};
var table = query.ToDataTable();
我还不能添加评论,所以你可以在这里做什么
根据下面的回答thread
您需要参考 FastMember
public static DataTable ToDataTable<T>(this IEnumerable<T> data)
{
if (data == null)
throw new ArgumentNullException("data");
var table = new DataTable("sd");
using (var reader = ObjectReader.Create(data))
{
table.Load(reader);
}
return table;
}
如果您使用的是 DataContext (linq-to-sql)
public static DataTable ToDataTable<T>(this IQueryable<T> query, DataContext context)
{
if (query == null)
{
throw new ArgumentNullException("query");
}
IDbCommand cmd = context.GetCommand(query.AsQueryable());
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = (SqlCommand)cmd;
DataTable dt = new DataTable("sd");
try
{
cmd.Connection.Open();
adapter.FillSchema(dt, SchemaType.Source);
adapter.Fill(dt);
}
finally
{
cmd.Connection.Close();
}
return dt;
}
已更新
你可以使用下面的功能
public static DataTable ConvertToDataTable(IEnumerable<XElement> data)
{
var table = new DataTable();
// create the columns
foreach(var xe in data.First().Descendants())
table.Columns.Add(xe.Name.LocalName,typeof(string));
// fill the data
foreach(var item in data)
{
var row = table.NewRow();
foreach(var xe in item.Descendants())
row[xe.Name.LocalName] = xe.Value;
table.Rows.Add(row);
}
return table;
}
并使用函数
var table = ConvertToDataTable(document.Descendants("orders"));
在这里工作sample