当前位置:  开发笔记 > 编程语言 > 正文

从与LINQ连接的两个DataTable创建组合的DataTable.C#

如何解决《从与LINQ连接的两个DataTable创建组合的DataTable.C#》经验,为你挑选了2个好方法。

我有以下代码填充dataTable1dataTable2两个简单的SQL查询,dataTableSqlJoined从相同的表填充,但连接在一起.

我正在尝试编写一个LINQ查询,它可以创建dataTableLinqJoined就像使用SQL 创建的那样.在下面的示例中,它仅返回dataTable1中的值.

SELECT遇到的问题是在linq查询中放入什么.如何创建包含DataRows中所有列的新DataRow.在运行时之前,我不会知道查询的确切列名/模式.

sqlCommand = new SqlCommand("SELECT ID, A, B FROM Table1", sqlConnection, sqlTransaction);
sqlAdapter = new SqlDataAdapter(sqlCommand);
DataTable dataTable1 = new DataTable();
sqlAdapter.Fill(dataTable1);

sqlCommand = new SqlCommand("SELECT ID, C, D FROM Table2", sqlConnection, sqlTransaction);
sqlAdapter = new SqlDataAdapter(sqlCommand);
DataTable dataTable2 = new DataTable();
sqlAdapter.Fill(dataTable2);

sqlCommand = new SqlCommand("SELECT Table1.ID, A, B, Table2.ID, C, D FROM Table1 INNER JOIN Table2 ON Table1.ID = Table2.ID", sqlConnection, sqlTransaction);
sqlAdapter = new SqlDataAdapter(sqlCommand);
DataTable dataTableSqlJoined = new DataTable();
sqlAdapter.Fill(dataTableSqlJoined);

var dataRows =
    from
        dataRows1 in dataTable1.AsEnumerable()
    join
        dataRows2 in dataTable2.AsEnumerable()
    on
        dataRows1.Field("ID") equals dataRows2.Field("ID")
    select
        dataRows1; // + dataRows2;

DataTable dataTableLinqJoined = dataRows.CopyToDataTable();

对于更多背景,组合查询是非常数据库密集的并且导致性能问题.第一个查询返回的数据是相当静态的,可以大量缓存.第二个查询返回的数据不断变化但运行速度很快,因此不需要缓存.还有很多代码依赖于组合DataTable的传递,因此在以不同格式传递数据时没有太多可行的选项可用.



1> Aaronaught..:

你看过这个页了吗?

HOW TO:在Visual C#.NET中实现DataSet JOIN辅助类

如果这种方法对你来说不够LINQy,你可以将行数据分解为对象数组:

DataTable targetTable = dataTable1.Clone();
var dt2Columns = dataTable2.Columns.OfType().Select(dc => 
    new DataColumn(dc.ColumnName, dc.DataType, dc.Expression, dc.ColumnMapping));
targetTable.Columns.AddRange(dt2Columns.ToArray());
var rowData =
    from row1 in dataTable1.AsEnumerable()
    join row2 in dataTable2.AsEnumerable()
        on row1.Field("ID") equals row2.Field("ID")
    select row1.ItemArray.Concat(row2.ItemArray).ToArray();
foreach (object[] values in rowData)
    targetTable.Rows.Add(values);

我认为这就像你能够做到的那样简洁,我会解释原因:它是架构.

A DataRow不是一个独立的对象; 这取决于它的拥有DataTable,没有它就无法生存.有没有支持的方法来创建一个"断开连接" DataRow; 该CopyToDataTable()扩展方法适用于已经存在在一个行DataTable,只是从源复制的模式(请记住,每一个DataRow都有它的父级的引用Table)复制行本身(最有可能使用之前ImportRow,虽然我还没有真正打开了反射来校验).

在这种情况下,您需要创建一个新架构.在您可以创建任何(新)行,你需要创建表来保存它们首先,这意味着在上述方法的顶部的3行代码写至少.

然后你最终可以创建行 - 但是一次只能创建一行,因为它DataTable和它的相关联DataRowCollection不会公开任何方法来一次添加多行.当然,您可以添加自己的扩展方法,DataRowCollection以使"看起来更好":

public static void AddRange(this DataRowCollection rc,
    IEnumerable tuples)
{
    foreach (object[] data in tuples)
        rc.Add(tuples);
}

然后你可以摆脱foreach第一种方法,并将其替换为:

targetTable.Rows.AddRange(rowData);

虽然这真的只是在改变冗长,而不是消除它.

最重要的是,只要你正在使用传统的DataSet类层次结构,总会有一点点瑕疵.Linq to DataSet扩展很好,但它们只是扩展,不能改变上面的限制.



2> suryakiran..:

Aaronaught很棒.但是想为LINQy代码添加一些增强功能.在将dataTable2中的列添加到Target表时,Target表中可能已存在少量列(我们正在加入).所以我们走了.

DataTable targetTable = dataTable1.Clone();
var dt2Columns = dataTable2.Columns.OfType().Select(dc => 
new DataColumn(dc.ColumnName, dc.DataType, dc.Expression, dc.ColumnMapping));
var dt2FinalColumns=from dc in dt2Columns.AsEnumerable()
                    where targetTable.Columns.Contains(dc.ColumnName) == false
                    select dc;
targetTable.Columns.AddRange(dt2FinalColumns.ToArray());
var rowData =from row1 in dataTable1.AsEnumerable()
             join row2 in dataTable2.AsEnumerable()
             on row1.Field("ID") equals row2.Field("ID")
             select row1.ItemArray.Concat(row2.ItemArray.Where(r2=> row1.ItemArray.Contains(r2)==false)).ToArray();
foreach (object[] values in rowData)
targetTable.Rows.Add(values);

希望这对像我这样的人有用.

推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有