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

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

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

MyDatabaseDataContext db = new MyDatabaseDataContext(conn); IEnumerable queryProjects = (from DataRow p in db.STREAM_PROJECTs.AsEnumerable() where p.Field("STREAM_ID") == StreamID select new { PROJECT_ID = p.Field("PROJECT_ID"), PROJECT_NAME = p.Field("PROJECT_NAME") }) as IEnumerable; DataTable results = queryProjects.CopyToDataTable(); 

 //(from p in db.STREAM_PROJECTs.AsEnumerable() //where p.STREAM_ID == StreamID //select new //{ // p.PROJECT_NAME, // p.PROJECT_ID //}) as IEnumerable; 

此线程中的示例似乎也不适用于这种情况。

我想我可以用老式的方式运行一个sql查询命令,但不是linq应该更快吗?

你的问题是这样的:

 as IEnumerable 

as关键字执行安全转换,而不是转换,您似乎可能认为它正在执行。 as关键字在语义上与执行此操作相同:

 IEnumerable queryProjects = (IEnumerable)(from DataRow p in db.STREAM_PROJECTs.AsEnumerable() where p.Field("STREAM_ID") == StreamID select new { PROJECT_ID = p.Field("PROJECT_ID"), PROJECT_NAME = p.Field("PROJECT_NAME") }); 

除了带有as的版本,如果它无法将您的查询对象(这是一个IQueryable ,其中T是一个匿名类型)转换为IEnumerable (它不是) as则不会抛出exception。

不幸的是,我没有内置的方法,它将采用一个具体的类型(如本例中的匿名类型),并将其转换为DataTable 。 编写一个不会太复杂,因为您基本上需要reflection性地获取属性然后迭代集合并使用这些属性在DataTable创建列。 我将在一些例子中发表一个例子。

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

 public static DataTable ToDataTable(this IEnumerable 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; }