C# 数据表上的LINQ查询

C# 数据表上的LINQ查询,c#,.net,linq,datatable,.net-3.5,C#,.net,Linq,Datatable,.net 3.5,我试图对DataTable对象执行LINQ查询,奇怪的是,我发现对DataTable执行这样的查询并不简单。例如: var results = from myRow in myDataTable where results.Field("RowNo") == 1 select results; 这是不允许的。我怎样才能让这样的东西工作 我很惊讶LINQ查询在数据表上是不允许的 并不是故意不允许在DataTables上使用它们,只是DataTables早于可以执行Linq查询的IQueryabl

我试图对DataTable对象执行LINQ查询,奇怪的是,我发现对DataTable执行这样的查询并不简单。例如:

var results = from myRow in myDataTable
where results.Field("RowNo") == 1
select results;
这是不允许的。我怎样才能让这样的东西工作


我很惊讶LINQ查询在数据表上是不允许的

并不是故意不允许在DataTables上使用它们,只是DataTables早于可以执行Linq查询的IQueryable和generic IEnumerable构造

这两个接口都需要某种排序类型的安全验证。数据表不是强类型的。例如,这就是为什么人们不能查询ArrayList的原因


要使Linq正常工作,您需要将结果映射到类型安全对象,并根据该对象进行查询。

您可以在Rows集合中使用Linq to对象,如下所示:

var results = from myRow in myDataTable.Rows where myRow.Field("RowNo") == 1 select myRow;
正如@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
使用系统数据//需要扩展方法才能工作
...
风险值结果=
从myDataTable.Rows中的myRow
其中myRow.Field(“RowNo”)==1
选择myRow//选择你想要的东西,而不是收藏

您还需要向
System.Data.DataSetExtensions

添加项目引用,因为
DataRowCollection
未实现
IEnumerable
,因此无法查询
DataTable
的行集合。您需要为
DataTable
使用
AsEnumerable()
扩展名。像这样:

var results = from myRow in myDataTable.AsEnumerable()
where myRow.Field<int>("RowNo") == 1
select myRow;
var query=来自dt.AsEnumerable()中的p
其中p.Field(“code”)==this.txtCat.Text
选择新的
{
名称=p.字段(“名称”),
年龄=p.字段(“年龄”)
};
name和age字段现在是查询对象的一部分,可以像这样访问:Console.WriteLine(query.name)

var results=来自tblCurrentStock.AsEnumerable()中的myRow
其中myRow.Field(“item_name”).ToUpper().StartsWith(tbSearchItem.Text.ToUpper())
选择myRow;
DataView=results.AsDataView();
//创建数据表
DataTable dt=新的DataTable();
dt.Columns.AddRange(新数据列[])
{
新数据列(“ID”,类型(System.Int32)),
新数据列(“名称”,类型(System.String))
});
//填充数据
Add(新对象[]{1,“Test1”});
Add(新对象[]{2,“Test2”});
//现在使用linq查询数据表
//要使用linq,应该需要我们的源代码实现IEnumerable接口。
//但是DataTable没有实现IEnumerable接口
//所以我们调用DataTable扩展方法,即AsEnumerable(),它将返回EnumerablerRowCollection
//现在查询DataTable以查找ID为1的行
DataRow drow=dt.AsEnumerable()。其中(p=>p.Field(0)==1.FirstOrDefault();
// 
试试这个

var row = (from result in dt.AsEnumerable().OrderBy( result => Guid.NewGuid()) select result).Take(3) ; 

对于VB.NET,代码如下所示:

Dim results = From myRow In myDataTable  
Where myRow.Field(Of Int32)("RowNo") = 1 Select myRow
from prod in TenMostExpensiveProducts().Tables[0].AsEnumerable()
where prod.Field<decimal>("UnitPrice") > 62.500M
select prod
FROM myDataTable
WHERE RowNo = 1
SELECT *
DataView view = new DataView(myDataTable);  //FROM myDataTable
view.RowFilter = "RowNo = 1";  //WHERE RowNo = 1
DataTable results = view.ToTable(true);  //SELECT *

最有可能的是,解决方案中已经定义了DataSet、DataTable和DataRow的类。如果是这种情况,则不需要DataSetExtensions引用

例如:数据集类名->自定义集,数据行类名->自定义表行(定义列:行号,…)

var result=来自myDataTable.Rows.OfType()中的myRow
其中myRow.RowNo==1
选择myRow;
或者(我更喜欢)

var result=myDataTable.Rows.OfType()。其中(myRow=>myRow.RowNo);

您可以通过linq使其优雅地工作,如下所示:

Dim results = From myRow In myDataTable  
Where myRow.Field(Of Int32)("RowNo") = 1 Select myRow
from prod in TenMostExpensiveProducts().Tables[0].AsEnumerable()
where prod.Field<decimal>("UnitPrice") > 62.500M
select prod
FROM myDataTable
WHERE RowNo = 1
SELECT *
DataView view = new DataView(myDataTable);  //FROM myDataTable
view.RowFilter = "RowNo = 1";  //WHERE RowNo = 1
DataTable results = view.ToTable(true);  //SELECT *
我更喜欢最后一种方法,而它是最灵活的。 注意:别忘了连接
System.Data.DataSetExtensions.dll
reference

var results=from myDataTable中的myRow
var results = from myRow in myDataTable
where results.Field<Int32>("RowNo") == 1
select results;
其中results.Field(“RowNo”)==1 选择结果;
试试这个

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 );
}
SqlCommand cmd=newsqlcommand(“从员工中选择*”,con);
SqlDataReader dr=cmd.ExecuteReader();
数据表dt=新数据表(“员工”);
dt.荷载(dr);
var Data=dt.AsEnumerable();
变量名称=从数据中的emp选择emp.字段(dt.列[1]);
foreach(名称中的变量名称)
{
Console.WriteLine(名称);
}

在我的应用程序中,我发现按照答案中的建议,使用带有DataTable的AsEnumerable()扩展名的LINQ to数据集速度非常慢。如果您对优化速度感兴趣,请使用James Newtonking的Json.Net库()

//将数据表序列化为json字符串
string serializedTable=JsonConvert.SerializeObject(myDataTable);
Jarray dataRows=Jarray.Parse(serializedTable);
//运行LINQ查询
列表结果=(来自dataRows中的行)
其中(int)行[“ans_键”]==42
选择row.ToList();
//如果需要将结果保存在数据表中
字符串jsonResults=JsonConvert.SerializeObject(结果);
DataTable resultsTable=JsonConvert.DeserializeObject(jsonResults);

这是一种适用于我并使用lambda表达式的简单方法:

var results = myDataTable.Select("").FirstOrDefault(x => (int)x["RowNo"] == 1)
然后,如果需要特定值:

if(results != null) 
    var foo = results["ColName"].ToString()
IEnumerable result=来自dataTableResult.AsEnumerable()中的myRow
选择myRow[“服务器”]。ToString();

我意识到这个问题已经被回答了好几次,但我只是想提供另一种方法:

我喜欢使用
.Cast()
方法,它有助于我在查看定义的显式类型时保持理智,我认为
.AsEnumerable()
无论如何都会调用它:

var results=来自myDataTable.Rows.Cast()中的myRow
其中myRow.Field(“RowNo”)==1选择myRow;

var results=myDataTable.Rows.Cast()
.FirstOrDefault(x=>x.Field(“行号”)==1);

如注释中所述,不需要
System.Data.DataSetExtensions
或任何其他程序集()

尝试以下简单的查询行:

var result=myDataTable.AsEnumerable().Where(myRow => myRow.Field<int>("RowNo") == 1);
var result=myDataTable.AsEnumerable()。其中(myRow=>myRow.Field(“RowNo”)==1);

下面提供了如何实现这一点的示例:

DataSet dataSet = new DataSet(); //Create a dataset
dataSet = _DataEntryDataLayer.ReadResults(); //Call to the dataLayer to return the data

//LINQ query on a DataTable
var dataList = dataSet.Tables["DataTable"]
              .AsEnumerable()
              .Select(i => new
              {
                 ID = i["ID"],
                 Name = i["Name"]
               }).ToList();
你可以试试这个,
if(results != null) 
    var foo = results["ColName"].ToString()
IEnumerable<string> result = from myRow in dataTableResult.AsEnumerable()
                             select myRow["server"].ToString() ;
var result=myDataTable.AsEnumerable().Where(myRow => myRow.Field<int>("RowNo") == 1);
DataSet dataSet = new DataSet(); //Create a dataset
dataSet = _DataEntryDataLayer.ReadResults(); //Call to the dataLayer to return the data

//LINQ query on a DataTable
var dataList = dataSet.Tables["DataTable"]
              .AsEnumerable()
              .Select(i => new
              {
                 ID = i["ID"],
                 Name = i["Name"]
               }).ToList();
List<MyClass> result = myDataTable.AsEnumerable().Select(x=> new MyClass(){
     Property1 = (string)x.Field<string>("ColumnName1"),
     Property2 = (int)x.Field<int>("ColumnName2"),
     Property3 = (bool)x.Field<bool>("ColumnName3"),    
});
                    //Json Formating code
                    //DT is DataTable
                    var filter = (from r1 in DT.AsEnumerable()

                                  //Grouping by multiple columns 
                                  group r1 by new
                                  {
                                      EMPID = r1.Field<string>("EMPID"),
                                      EMPNAME = r1.Field<string>("EMPNAME"),

                                  } into g
                                  //Selecting as new type
                                  select new
                                  {

                                      EMPID = g.Key.EMPID,
                                      MiddleName = g.Key.EMPNAME});
DataView view = new DataView(myDataTable); 
view.RowFilter = "RowNo = 1";
DataTable results = view.ToTable(true);
SELECT *
FROM myDataTable
WHERE RowNo = 1
FROM myDataTable
WHERE RowNo = 1
SELECT *
DataView view = new DataView(myDataTable);  //FROM myDataTable
view.RowFilter = "RowNo = 1";  //WHERE RowNo = 1
DataTable results = view.ToTable(true);  //SELECT *