使用DataContext从LINQ查询填充DataTable的最快方法

时间:2011-02-10 04:00:05

标签: c# asp.net linq datatable ienumerable

我正在尝试运行linq查询,但我需要将结果作为数据表,因为我使用它来存储来自同一viewstate对象中不同查询的记录。

下面的两个版本编译,但返回一个空集。确切的错误是“值不能为空。 参数名称:source“。(是的,我已检查过数据):

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应该更快吗?

1 个答案:

答案 0 :(得分:19)

你的问题是:

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是匿名类型)转换为{时,不会引发异常{1}}(事实并非如此)。

不幸的是,我没有内置的方法可以采用可枚举的具体类型(比如本例中的匿名类型)并将其转换为IEnumerable<DataRow>。编写一个不会太复杂,因为您基本上需要反射性地获取属性,然后遍历集合并使用这些属性在DataTable中创建列。我将在一些例子中发布一个例子。

这样的东西放在你DataTable的命名空间中的静态类中,应该提供一个可以做你想做的扩展方法:

using