C# 使用联接将Linq到数据集查询的结果加载到datatable中

C# 使用联接将Linq到数据集查询的结果加载到datatable中,c#,linq,linq-to-dataset,C#,Linq,Linq To Dataset,我有一个linq到数据集的查询,它连接两个表并从每个表中提取所需的参数。我需要将它们放入DataTable以绑定到DataGridView。我发现在上执行此操作的示例是一个从单个表中获取单个值的简单示例,但当我尝试更改查询以遵循它时,我无法这样做。CopyToDataTable()方法要求将查询分配给IEnumerable,但当我这样做时,我被告知需要显式转换;但强制转换在运行时失败,但有一个例外: 无法强制转换类型为“d_u61`4[System.Data.DataRow,System.Dat

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

无法强制转换类型为“d_u61`4[System.Data.DataRow,System.Data.DataRow,System.Int32,f_uAnonymousType0`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
    });
var query=MyDataSet.Table1.AsEnumerable().Join(MyDataSet.Table2.AsEnumerable(),
table1=>table1.字段(“table1_Id”),
table2=>table2.字段(“Table1_Id”),
(表1、表2)=>新
{
Table1ID=table1.字段(“table1\u Id”)
//注释掉其他参数以简化示例
});
具有显式强制转换的非工作查询:

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
    });
IEnumerable查询=(IEnumerable)MyDataSet.Table1.AsEnumerable().Join(MyDataSet.Table2.AsEnumerable(),
table1=>table1.字段(“table1_Id”),
table2=>table2.字段(“Table1_Id”),
(表1、表2)=>新
{
Table1ID=table1.字段(“table1\u Id”)
//注释掉其他参数以简化示例
});

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

要使第二个工作正常,您需要以下内容:

var query = ... => new DataRow() 
{
});
但这是行不通的,因为DataRow没有公共构造函数,不能以这种方式初始化

因此,使用第一个并迭代结果(注意,我在这里有一点猜测,您必须首先为表3设置列):

编辑:
如果您分别对上述3个步骤计时,您可能会发现第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);

        }
//我已经创建了具有AddressID、Name srting和LastName字符串的datatable地址
数据集ds=新数据集();
ds.Tables[“Address”].Rows.Add(新对象[]{1,“Priya”,“Patel”});
ds.Tables[“Address”].Rows.Add(新对象[]{2,“Bunty”,“Rayapati”});
ds.Tables[“Address”].Rows.Add(新对象[]{3,“Birva”,“Parikh”});
//我已经创建了具有AddressTypeID int32和State-string的DataTableAddressType
ds.Tables[“AddressType”].Rows.Add(新对象[]{1,“Virginia”});
ds.Tables[“AddressType”].Rows.Add(新对象[]{2,“内布拉斯加州”});
ds.Tables[“AddressType”].Rows.Add(新对象[]{3,“Philadeplhia”});
DataTable dt1=ds.Address.CopyToDataTable();
DataTable dt2=ds.AddressType.CopyToDataTable();
DataTable dt3=新的DataTable();
var query=dt1.AsEnumerable().Join(dt2.AsEnumerable(),
dmt1=>dmt1.Field(“AddressID”),
dmt2=>dmt2.Field(“AddressTypeID”),
(dmt1、dmt2)=>新
{
Table1ID=dmt1.字段(“地址ID”)
//注释掉其他参数以简化示例
});
query.ToList();
//FullAddress是我的第三个数据表,它有助于
foreach(查询中的变量行)
{
var r=ds.FullAddress.NewRow();
r[“AID”]=表1ID行;
ds.FullAddress.Rows.Add(r.ItemArray);
}

我正面临这样的错误,因为
在LINQ查询中的许多JOIN语句之后,
编译器
创建连接所有模型的新类型

所以很难直接投进去

但是,如果您知道结果只包含一个特定的模型,那么您可以再执行一个步骤来帮助编译器强制转换它,即

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();
    }
公共静态IList GetDepartmentLetters(int departmentId)
{
IEnumerable allDepartmentLetters=来自LetterService.GetAllLetters()中的allLetter
将allLetter.EmployeeID等于allUser.ID的UserService.GetAllUsers()中的allUser加入到usersGroub中
来自usersGroub.DefaultIfEmpty()中的用户
在user.DepartmentID等于allDepartment.ID的DepartmentService.GetAllDepartments()中加入allDepartment
其中allDepartment.ID==部门ID
选择allLetter;
返回所有部门信函。ToArray();
}

如果你的解决方案不那么优雅,那么它的运行速度大约是原来的3倍。不过,时间的流逝令人沮丧。我的10k测试集运行linq查询大约需要0.05秒,将结果转换为数据表需要1.35秒。foreach实际上正在获取记录。我会编辑的。在这种情况下,linq似乎并没有增加多少。运行查询并根据结果创建datatable只比直接搜索datatable快3%。我不知道您对Linq的期望是什么。它很少会比其他任何东西都快,只是更方便。请不要只提供代码答案。为什么这是答案?看看这个链接(向下滚动到“创建自定义CopyToDataTable方法”部分)
MyListOfTypeIEnumerable.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();
    }