我试图从MSDN的代码示例中学习,但我显然不理解LINQ的真正工作原理。我想要做的是为一个“查找窗口”填充一个DataGridView,其中包含来自强类型数据集的表中可用列的子集。我正在尝试以下方法:
IEnumerable<DataRow> query =
(from t in DataAccess.ds.GL40200.AsEnumerable()
where t.SGMTNUMB == 3
select new { t.SGMNTID, t.DSCRIPTN });
DataTable myTable = query.CopyToDataTable<DataRow>();
dgv_Exhibitors.DataSource = myTable;
但是,这会引发从EnumerableRowCollection<AnonymousType#1>
到IEnumerable<System.Data.DataRow>
的隐式转换错误。
我尝试添加以下内容,但会导致运行时错误:
select new { t.SGMNTID, t.DSCRIPTN }).Cast<DataRow>();
虽然只选择't',但该表包含我不想向用户显示的列:
where t.SGMTNUMB == 3
select t;
您可以使用一种简单的方法来帮助您使用两个所需的列填充DataGridView吗?如果感觉比使用LINQ更好或更容易,我会接受建议。
答案 0 :(得分:1)
失败是因为您的select
语句正在创建一个包含两个字段的匿名类。它不再是DataRow
,编译器也不知道如何通过DataRow
将其强制转换回Cast<T>()
。
一种选择是坚持使用有效的方法,然后只需隐藏您不希望在DataGridView
中看到的列:
dgv_Exhibitors.DataSource =
DataAccess.ds.GL40200.AsEnumerable().Where(t => t.SGMTNUMB == 3).CopyToDataTable();
foreach (var col in dgv_Exhibitors.Columns.Cast<DataGridViewColumn>()
.Where(c => c.Name != "SGMNTID" && c.Name != "DSCRIPTN"))
{
col.Visible = false;
}
或者,设置AutoGenerateColumns = false
,然后只需定义要查看的列,并将其添加到DataGridView.Columns
集合中。
另一个选择是使用您现有的方法,但在其上调用ToList()
,并且不要试图将其转换回DataTable
。 DataGridView
可以显示任何集合:
dgv_Exhibitors.DataSource = (from t in DataAccess.ds.GL40200.AsEnumerable()
where t.SGMTNUMB == 3
select new { t.SGMNTID, t.DSCRIPTN }).ToList();
答案 1 :(得分:0)
扩展Grant Winney的回答,使用var代替IEnumerable <DataRow>
来接收匿名类型。
var query =
(from t in DataAccess.ds.GL40200.AsEnumerable()
where t.SGMTNUMB == 3
select new { t.SGMNTID, t.DSCRIPTN });
如果你想在Datatable中得到结果,你必须创建一个并逐个添加值。
DataTable myTable = new DataTable();
myTable.Columns.Add("SGMNTID", typeof(int));
myTable.Columns.Add("DSCRIPTN", typeof(string));
foreach (var x in query)
{
DataRow dr = myTable.NewRow();
dr[0] = x.SGMNTID;
dr[1] = x.DSCRIPTN;
myTable.Rows.Add(dr);
}
dgv_Exhibitors.DataSource = myTable;