使用DataContext从LINQ查询填充DataTable最快的方法
问题描述:
我想运行一个linq查询,但我需要结果作为datatable,因为我用它来存储来自不同查询的记录在同一个viewstate对象中。使用DataContext从LINQ查询填充DataTable最快的方法
以下两个版本编译,但返回一个空集。确切的错误是“值不能为空 参数名称:源”。 (是的,我已经检查有数据):
MyDatabaseDataContext db = new MyDatabaseDataContext(conn);
IEnumerable<DataRow> queryProjects =
(from DataRow p in db.STREAM_PROJECTs.AsEnumerable()
where p.Field<int>("STREAM_ID") == StreamID
select new
{
PROJECT_ID = p.Field<int>("PROJECT_ID"),
PROJECT_NAME = p.Field<string>("PROJECT_NAME")
}) as IEnumerable<DataRow>;
DataTable results = queryProjects.CopyToDataTable<DataRow>();
...
//(from p in db.STREAM_PROJECTs.AsEnumerable()
//where p.STREAM_ID == StreamID
//select new
//{
// p.PROJECT_NAME,
// p.PROJECT_ID
//}) as IEnumerable<DataRow>;
在此thread的例子似乎并没有在这种情况下,以工作,要么。
我想我可以运行一个SQL查询命令的老式的方式,但不是linq应该更快?
答
你的问题是这样的:
as IEnumerable<DataRow>
的as
关键字进行安全投,而不是一个转换,这好像你可能会认为它做的。该as
关键字是语义相同,这样做:
IEnumerable<DataRow> queryProjects =
(IEnumerable<DataRow>)(from DataRow p in db.STREAM_PROJECTs.AsEnumerable()
where p.Field<int>("STREAM_ID") == StreamID
select new
{
PROJECT_ID = p.Field<int>("PROJECT_ID"),
PROJECT_NAME = p.Field<int>("PROJECT_NAME")
});
除非as
版本时,它不能投你的查询对象(这是一个IQueryable<T>
,其中T
是一个匿名类型)将不会抛出异常到IEnumerable<DataRow>
(它不是)。
不幸的是,没有内建的方法,我知道这将采取一个具体类型的枚举(如在这个例子中的匿名类型),并将其变为DataTable
。编写一个不会太复杂,因为您基本上需要反射性地获取属性,然后遍历集合并使用这些属性在DataTable
中创建列。我会在一些例子中发布一个例子。
这样的事情,放在一个静态类,你是using
一个命名空间中,应该提供一个扩展方法,将你想要做什么:
public static DataTable ToDataTable<T>(this IEnumerable<T> source)
{
PropertyInfo[] properties = typeof(T).GetProperties();
DataTable output = new DataTable();
foreach(var prop in properties)
{
output.Columns.Add(prop.Name, prop.PropertyType);
}
foreach(var item in source)
{
DataRow row = output.NewRow();
foreach(var prop in properties)
{
row[prop.Name] = prop.GetValue(item, null);
}
output.Rows.Add(row);
}
return output;
}
我看 - 所以它只是隐藏InvalidCastException的?那么我如何才能将它放入数据表? – JumpingJezza 2011-02-10 04:23:42