将Linq转换为IEnumerable <datarow> </datarow>

时间:2011-06-03 15:13:09

标签: c# linq

我正在创建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;
}

5 个答案:

答案 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>();