【问题标题】:Load result of Linq-to-DataSet query with join into datatable将带有连接的 Linq-to-DataSet 查询的结果加载到数据表中
【发布时间】:2009-12-09 20:50:51
【问题描述】:

我有一个 Linq 到数据集查询,它连接两个表并从每个表中提取所需的参数。我需要将它们放入DataTable 以绑定到DataGridView。我在MSDN 上找到的用于执行此操作的示例是一个从单个表中获取单个值的简单示例,但是当我尝试更改查询以遵循它时,我无法这样做。 CopyToDataTable() 方法要求将查询分配给IEnumerable<DataRow>,但是当我这样做时,我被告知需要显式转换;但强制转换在运行时失败,但有以下异常:

无法转换类型为“d__61`4[System.Data.DataRow,System.Data.DataRow,System.Int32,f__AnonymousType0`1[System.Int32]]'的对象 输入 'System.Collections.Generic.IEnumerable`1[System.Data.DataRow]'。

原始工作查询:

var query = MyDataSet.Table1.AsEnumerable().Join(MyDataSet.Table2.AsEnumerable(),
    table1 => table1.Field<Int32>("Table1_Id"),
    table2 => table2.Field<Int32>("Table1_Id"),
    (table1, table2) => new
    {
        Table1ID = table1.Field<Int32>("Table1_Id")
        //Other parameters commented out to simplify the example
    });

显式转换的非工作查询:

IEnumerable<DataRow> query = (IEnumerable<DataRow>)MyDataSet.Table1.AsEnumerable()
                                             .Join(MyDataSet.Table2.AsEnumerable(),
    table1 => table1.Field<Int32>("Table1_Id"),
    table2 => table2.Field<Int32>("Table1_Id"),
    (table1, table2) => new
    {
        Table1ID = table1.Field<Int32>("Table1_Id")
        //Other parameters commented out to simplify the example
    });

【问题讨论】:

标签: c# linq linq-to-dataset


【解决方案1】:

在这两种情况下,您都在创建一个新的“匿名类型”来存储结果。

要使第二个工作,您需要类似的东西:

var query = ... => new DataRow() 
{
});

除了那行不通,因为 DataRow 没有公共构造函数并且不能以这种方式初始化。

所以,使用第一个并迭代结果(请注意,我在这里猜测了一点,您必须先为 table3 设置列):

foreach (var row in query)
{
   var r = table3.NewRow();
   r["Table1ID"] = row.Table1ID;
   r["Table2ID"] = row.Table1ID;                
}

编辑:

 var query = ...;  // step 1

 query = query.ToList();  // add this,  step 2

 foreach(...) { }  // step 3

如果您分别为上述 3 个步骤计时,您可能会发现第 2 步花费的时间最多。

【讨论】:

  • 如果不是那么优雅,您的解决方案也可以工作,而且速度也快 3 倍。
  • 虽然时间流逝的细分令人沮丧。我的 10k 测试集运行 linq 查询大约需要 0.05 秒,将结果转换为 DataTable 需要 1.35 秒。
  • Dan,Linq 有一种叫做延迟执行的东西。 foreach 实际上是在获取记录。我会编辑。
  • 啊。在那种情况下,linq 似乎并没有真正增加太多。运行查询并根据结果创建数据表仅比直接遍历数据表快 3%。
  • 我不知道你对 Linq 有什么期望。它很少会比其他任何东西都快,只是更方便。
【解决方案2】:

您好,这是另一种方法..

        //I have created datatable Address having AddressID<int32>,Name-srting,LastName-string
        DataSet ds= new DataSet();
        ds.Tables["Address"].Rows.Add(new object[] { 1, "Priya", "Patel" });
        ds.Tables["Address"].Rows.Add(new object[] { 2, "Bunty", "Rayapati" });
        ds.Tables["Address"].Rows.Add(new object[] { 3, "Birva", "Parikh" });
        //i have created Datatable AddressType having AddressTypeID int32 and State- string
        ds.Tables["AddressType"].Rows.Add(new object[] { 1, "Virginia" });
        ds.Tables["AddressType"].Rows.Add(new object[] { 2, "Nebraska" });
        ds.Tables["AddressType"].Rows.Add(new object[] { 3, "Philadeplhia" });

        DataTable dt1 = ds.Address.CopyToDataTable(); 
        DataTable dt2 = ds.AddressType.CopyToDataTable();
        DataTable dt3 = new DataTable();

        var query = dt1.AsEnumerable().Join(dt2.AsEnumerable(),
            dmt1 => dmt1.Field<Int32>("AddressID"),
                dmt2 => dmt2.Field<Int32>("AddressTypeID"),
        (dmt1, dmt2) => new 
        {
            Table1ID = dmt1.Field<Int32>("AddressID")
            //Other parameters commented out to simplify the example
        });
        query.ToList();
        //FullAddress is my third Datatable is having AID
        foreach (var row in query)
        {
            var r = ds.FullAddress.NewRow();
            r["AID"] = row.Table1ID;
            ds.FullAddress.Rows.Add(r.ItemArray);

        }

【讨论】:

  • 请不要只提供仅代码的答案。为什么这是答案?
【解决方案3】:

我遇到了这样的错误,因为 after many joins statements 在您的 LINQ 查询中编译器 create new type that concatenate all your models

所以很难直接投进去

但如果您知道结果只包含一个特定的模型,您可以再做一步来帮助编译器进行转换,即

MyListOfTypeIEnumerable.ToArray()

看看我的问题,ToArray() 解决它

public static IList<Letter> GetDepartmentLetters(int departmentId)
    {
        IEnumerable<Letter> allDepartmentLetters = from allLetter in LetterService.GetAllLetters()
            join allUser in UserService.GetAllUsers() on allLetter.EmployeeID equals allUser.ID into usersGroub
            from user in usersGroub.DefaultIfEmpty()
            join allDepartment in DepartmentService.GetAllDepartments() on user.DepartmentID equals allDepartment.ID
            where allDepartment.ID == departmentId
            select allLetter;
        return allDepartmentLetters.ToArray();
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-11
    • 2014-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多