我试图在数据表对象上执行LINQ查询,奇怪的是,我发现在数据表上执行这样的查询并不简单。例如:
var results = from myRow in myDataTable
where results.Field("RowNo") == 1
select results;
这是不允许的。我怎么才能让这样的东西工作呢?
我很惊讶,LINQ查询不允许在数据表上!
我试图在数据表对象上执行LINQ查询,奇怪的是,我发现在数据表上执行这样的查询并不简单。例如:
var results = from myRow in myDataTable
where results.Field("RowNo") == 1
select results;
这是不允许的。我怎么才能让这样的东西工作呢?
我很惊讶,LINQ查询不允许在数据表上!
当前回答
并不是故意不允许在DataTables上使用,只是DataTables早于IQueryable和IEnumerable构造,而Linq可以在这些构造上执行查询。
这两个接口都需要某种排序类型安全验证。数据表不是强类型的。这和人们不能查询数组列表的原因是一样的。
为了让Linq工作,你需要将你的结果映射到类型安全的对象上,并对其进行查询。
其他回答
IEnumerable<string> result = from myRow in dataTableResult.AsEnumerable()
select myRow["server"].ToString() ;
我提出以下解决方案:
DataView view = new DataView(myDataTable);
view.RowFilter = "RowNo = 1";
DataTable results = view.ToTable(true);
查看DataView文档,我们首先看到的是:
表示数据表的可数据化、自定义视图,用于排序、过滤、搜索、编辑和导航。
我从中得到的是,DataTable仅用于存储数据,而DataView则允许我们对DataTable进行“查询”。
下面是这个特殊情况下的工作原理:
您尝试实现SQL语句
SELECT *
FROM myDataTable
WHERE RowNo = 1
“数据表语言”。在c#中,我们可以这样读:
FROM myDataTable
WHERE RowNo = 1
SELECT *
在c#中是这样的:
DataView view = new DataView(myDataTable); //FROM myDataTable
view.RowFilter = "RowNo = 1"; //WHERE RowNo = 1
DataTable results = view.ToTable(true); //SELECT *
我知道这个问题已经被回答过很多次了,但我只想提供另一种方法:
我喜欢使用.Cast<T>()方法,它可以帮助我在看到定义的显式类型时保持理智,并且我认为.AsEnumerable()无论如何都会调用它:
var results = from myRow in myDataTable.Rows.Cast<DataRow>()
where myRow.Field<int>("RowNo") == 1 select myRow;
or
var results = myDataTable.Rows.Cast<DataRow>()
.FirstOrDefault(x => x.Field<int>("RowNo") == 1);
如注释中所述,不需要System.Data.DataSetExtensions或任何其他程序集(参考)
并不是故意不允许在DataTables上使用,只是DataTables早于IQueryable和IEnumerable构造,而Linq可以在这些构造上执行查询。
这两个接口都需要某种排序类型安全验证。数据表不是强类型的。这和人们不能查询数组列表的原因是一样的。
为了让Linq工作,你需要将你的结果映射到类型安全的对象上,并对其进行查询。
试试这个…
SqlCommand cmd = new SqlCommand( "Select * from Employee",con);
SqlDataReader dr = cmd.ExecuteReader( );
DataTable dt = new DataTable( "Employee" );
dt.Load( dr );
var Data = dt.AsEnumerable( );
var names = from emp in Data select emp.Field<String>( dt.Columns[1] );
foreach( var name in names )
{
Console.WriteLine( name );
}