我正在尝试在DataTable对象上执行LINQ查询,但奇怪的是我发现在DataTable上执行这样的查询并不简单。例如:
var results = from myRow in myDataTable
where results.Field("RowNo") == 1
select results;
这是不允许的。我该如何使类似的东西工作起来?
我很惊讶LINQ查询在DataTable上是不允许的!
由于DataRowCollection
没有实现IEnumerable<T>
,所以您无法对DataTable
的Rows集合进行查询。 您需要使用DataTable
的AsEnumerable()
扩展方法。像这样:
var results = from myRow in myDataTable.AsEnumerable()
where myRow.Field<int>("RowNo") == 1
select myRow;
正如@Keith所说,您需要添加对System.Data.DataSetExtensions的引用。
AsEnumerable()
返回IEnumerable<DataRow>
。如果您需要将IEnumerable<DataRow>
转换为DataTable
,请使用CopyToDataTable()
扩展。
下面是一个使用Lambda表达式的查询示例:
var result = myDataTable
.AsEnumerable()
.Where(myRow => myRow.Field<int>("RowNo") == 1);
using System.Data;
。 - Luke DuddridgemyDataTable.Rows
即可。 - The ConspiracymyDataTable.Rows
,是因为myRow
变量被明确转换为DataRow
。在编译时,查询被重写为myDataTable.Rows.Cast<DataRow>().Where(myRow => (int)myRow["RowNo"] == 1)
。就个人而言,我并不认为调用AsEnumerable()
比调用Cast<DataRow>()
更复杂。据我所知,它们的性能相同,所以这只是一个偏好问题。 - Collin Kvar results = from DataRow myRow in myDataTable.Rows
where (int)myRow["RowNo"] == 1
select myRow
myRow.Field<int>("RowNo")
替换了 (int)myRow["RowNo"]
以更方便地支持可空类型。 - Jonas并不是因为DataTable故意不允许使用,而是因为DataTable在IQueryable和generic IEnumerable构造之前就已经存在了,而Linq查询需要这些接口的支持。
这两个接口都需要某种类型安全验证,而DataTable没有强类型。这也是为什么人们不能对ArrayList进行查询的原因。
要使Linq工作,您需要将结果映射到类型安全的对象上,并对其进行查询。
@ch00k所说:
using System.Data; //needed for the extension methods to work
...
var results =
from myRow in myDataTable.Rows
where myRow.Field<int>("RowNo") == 1
select myRow; //select the thing you want, not the collection
您还需要添加对System.Data.DataSetExtensions
的项目引用。
myRow
上放置特定类型或在Rows
上使用Cast<DataRow>()
。最好使用AsEnumerable()
。 - NetMageSystem.Linq
和 System.Data.DataSetExtensions
,那么 myDataTable.Rows
就会返回一个可枚举的 DataRow
集合。虽然这可能已经改变了,毕竟我已经十年没用它了。 - KeithDataSet
扩展没有被包含在 .NET Core 或 .NET Standard 中,因为当我回答这个问题时它们已经过时了。我真的不会在新项目中使用 DataSet
,因为有更好的数据访问模型,无论是编码的简便性还是性能方面。 - KeithDataRowCollection
没有实现 IEnumerable<T>
,只有 IEnumerable
,因此无法与强类型的 LINQ 一起使用。 - NetMage我知道这个问题已经被回答了几次,但是我想提供另一种方法:
我喜欢使用.Cast<T>()
方法,它帮助我保持清晰,看到明确定义的类型,而且我认为.AsEnumerable()
方法在深层调用它:
var results = from myRow in myDataTable.Rows.Cast<DataRow>()
where myRow.Field<int>("RowNo") == 1 select myRow;
或者var results = myDataTable.Rows.Cast<DataRow>()
.FirstOrDefault(x => x.Field<int>("RowNo") == 1);
正如评论中所指出的那样,不需要System.Data.DataSetExtensions
或任何其他程序集(参考文献)
var query = from p in dt.AsEnumerable()
where p.Field<string>("code") == this.txtCat.Text
select new
{
name = p.Field<string>("name"),
age= p.Field<int>("age")
};
现在姓名和年龄字段是查询对象的一部分,可以像这样访问:Console.WriteLine(query.name);
MessageBox.Show(name)
是未定义的。 - user1372430使用 LINQ 操作 DataSet/DataTable 数据
var results = from myRow in tblCurrentStock.AsEnumerable()
where myRow.Field<string>("item_name").ToUpper().StartsWith(tbSearchItem.Text.ToUpper())
select myRow;
DataView view = results.AsDataView();
System.Data.DataSetExtensions
。 - Louis Waweru//Create DataTable
DataTable dt= new DataTable();
dt.Columns.AddRange(new DataColumn[]
{
new DataColumn("ID",typeof(System.Int32)),
new DataColumn("Name",typeof(System.String))
});
//Fill with data
dt.Rows.Add(new Object[]{1,"Test1"});
dt.Rows.Add(new Object[]{2,"Test2"});
//Now Query DataTable with linq
//To work with linq it should required our source implement IEnumerable interface.
//But DataTable not Implement IEnumerable interface
//So we call DataTable Extension method i.e AsEnumerable() this will return EnumerableRowCollection<DataRow>
// Now Query DataTable to find Row whoes ID=1
DataRow drow = dt.AsEnumerable().Where(p=>p.Field<Int32>(0)==1).FirstOrDefault();
//
试试这个简单的查询语句:
var result=myDataTable.AsEnumerable().Where(myRow => myRow.Field<int>("RowNo") == 1);
您可以像这样在行集合上使用LINQ to objects:
var results = from myRow in myDataTable.Rows where myRow.Field("RowNo") == 1 select myRow;
DataTable.Rows
没有实现 IEnumerable
,我无法看出这个查询如何编译。 - onedaywhen
dt.Rows["FirstName]
垃圾体验更好。使用强类型表格(在项目中添加一个DataSet类型文件并在可视化设计器中创建表格),你只需编写例如myStronglyTpedDataset.Person.Where(p => p.FirstName == "John")
- 所有使其发生的魔法都已经完成。 - Caius JardAsEnumerable()
调用。不知道为什么需要那么多答案。 - Gert Arnold