我正在创建winForm应用程序,在Onbutton中单击我从两个数据库Mysql和Sqlite数据库中收集数据表。 在将Linq查询强制转换为IEnumerable以使获取查询值到DataTable以在DataGrid视图中显示时,我收到了Casting错误。
private void button1_Click(object sender, EventArgs e)
{
var obj = new table1TableAdapter(); //Mysql Table Adapter
var obj2 = new Table1TableAdapter(); // Sqlite Table Adapter
var ds = new DataSet();
ds.Tables.Add(obj.GetData());
ds.Tables.Add(obj2.GetData());
var tab1 = ds.Tables[0];
var tab2 = ds.Tables[1];
var query = from o in tab1.AsEnumerable()
join od in tab2.AsEnumerable()
on o.Field<string>("Name") equals od.Field<string>("Name")
select new
{
Name = o.Field<string>("Name"),
Rollno = od.Field<Int64>("rollno"),
Book = o.Field<string>("Book")
};
var q2 = (IEnumerable<DataRow>)query; //Unable to cast object of type <JoinIterator>
DataTable orderTable = q2.CopyToDataTable();
dataGridView1.DataSource = orderTable;
}
答案 0 :(得分:6)
看看你的代码,我会说,为什么要把它投到IEnumerable<DataRow>
呢?只需将查询绑定到GridView即可。
dataGridView1.DataSource = query.ToList();
答案 1 :(得分:4)
那是因为您要返回的查询对象与DataRow
无关。 query
将成为IEnumerable&lt; SomeAnonymousType &gt;。如何转换为DataRow
?
您需要更改语句以生成DataRow:
select new DataRow(/* Whatever Params */) { /* More Params */ };
然后它本身就是IEnumerable<DataRow>
,不需要投射。
答案 2 :(得分:3)
由于您的查询正在创建IEnumerable,因此无法将其强制转换为DataRow。我也不会建议使用select new DataRow(/ * Whatever Params /){/ More Params * /};因为这不是真正的DataRow对象,并且会是不好的做法。
我会这样处理它。即使这是一个小项目,Button_Click处理程序中也不应该有那么多代码。
首先,创建一个容器对象,将其称为DTO或ViewModel。我建议后者。
public class BookViewModel
{
public string Name { get; set; }
public Int64 Rollno { get; set; }
public string Book { get; set; }
}
接下来,创建一个将执行SQL查询的新类。这将使您的数据访问逻辑与表单逻辑分离。
public class BookService
{
public IList<BookViewModel> GetBookViewModel()
{
var obj = new table1TableAdapter(); //Mysql Table Adapter
var obj2 = new Table1TableAdapter(); // Sqlite Table Adapter
var ds = new DataSet();
ds.Tables.Add(obj.GetData());
ds.Tables.Add(obj2.GetData());
var tab1 = ds.Tables[0];
var tab2 = ds.Tables[1];
var query = from o in tab1.AsEnumerable()
join od in tab2.AsEnumerable()
on o.Field<string>("Name") equals od.Field<string>("Name")
select new BookViewModel
{
Name = o.Field<string>("Name"),
Rollno = od.Field<Int64>("rollno"),
Book = o.Field<string>("Book")
};
return query.ToList();
}
}
最后,将List绑定到您的显示器。
private void button1_Click(object sender, EventArgs e)
{
BookService bookService = new BookService();
dataGridView1.DataSource = bookService.GetBookViewModel();
}
现在,当您返回更改代码时,您将能够轻松修改显示逻辑,而无需阅读所有混合代码。
示例:
private void button1_Click(object sender, EventArgs e)
{
BookService bookService = new BookService();
IList<BookViewModel> books = bookService.GetBookViewModel();
if (books.Count == 0)
{
Label1.Text = "Sorry no books were found";
}
dataGridView1.DataSource = books;
}
答案 3 :(得分:1)
首先,您无法转换为IEnumerable,因为您查询本身并未生成DataRows
select new
{
Name = o.Field<string>("Name"),
Rollno = od.Field<Int64>("rollno"),
Book = o.Field<string>("Book")
};
正在创建一个匿名类型。
首先必须以某种方式将其更改为DataRow,然后将其转换为IEnumerable。
答案 4 :(得分:0)
我正在使用以下声明,这对我有用
UC070_WizardStepFilesDataSet.AllDossierDetailResultsRow[] searchrows =
(from a in _wizardStepPreviewDataSet.AllDossierDetailResults
where a.WingsSetNbr == row.WingsSetNbr && !a.BookCode.StartsWith("V")
select a).ToArray<UC070_WizardStepFilesDataSet.AllDossierDetailResultsRow>();