【问题标题】:Use .Select().Join() to Join Two DataTables使用 .Select().Join() 连接两个数据表
【发布时间】:2018-06-28 01:36:19
【问题描述】:

我一直在寻找高处和低处,但无济于事。我有两个数据表,我想加入 而不 创建一个新的结果表,因为我只需要更新其中一个表中的一些行以显示在网格视图中,类似于下面的代码,但是加入:

sage_invoices.Select("CCE2 IS NULL")
                .ToList<DataRow>()
                .ForEach(row =>
                {
                    row["Error"] = 1;
                    row["ErrorMessage"] = "Missing Region Code (Dimension 2 - CCE2)";
                });

我发现的所有内容都会生成一个新的输出数据表,类似于以下代码:

var collection = from t1 in dt1.AsEnumerable()
         join t2 in dt2.AsEnumerable()
         on t1["id"] equals t2["id"]
         select new { T1 = t1, T2 = t2 };

我找不到的是如何使用 .Join 连接两个数据表:

sage_invoices.Select()
                .Join(<What Goes here?>)
                .ToList<DataRow>()
                .ForEach(row =>
                {
                    row["Error"] = 1;
                    row["ErrorMessage"] = "ITMREF is not a Sage Product Code";
                });

如果有人能指出我正确的方向,我将不胜感激。

谢谢 加雷斯

【问题讨论】:

标签: c# linq join datatable


【解决方案1】:

我通常通过构建一个匿名对象来完成此操作,该对象通过 Join 或 GroupJoin 包含对我的源对象和目标对象的引用,然后循环访问 Join 的结果以更新我的目标对象。请参阅下面的示例。

查看JoinGroupJoin 上的文档。 Join 非常适合 1-1 匹配,而 GroupJoin 是 0-* 匹配(如 SQL 左连接)。 Join 和 GroupJoin 的参数允许您为每个 IEnumerable 指定一个选择器函数,然后为输出对象指定一个选择器函数。请注意,下面的t1t2 指的是table1table2

using System;
using System.Data;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var table1 = GetEmptyTable();
        table1.Rows.Add(1, "Old Value", false);
        table1.Rows.Add(2, "Untouched Value", false);

        var table2 = GetEmptyTable();
        table2.Rows.Add(1, "New Value", false);
        table2.Rows.Add(3, "Unused Value", false);

        Console.WriteLine("Before...");
        Console.WriteLine(PrintTable(table1));

        var matched = table1.Select()
            .Join(table2.Select(), t1 => (int)t1["A"], t2 => (int)t2["A"], (t1, t2) 
=> new
            {
                DestinationRow = t1,
                SourceRow = t2
            });
        foreach (var match in matched)
        {
            match.DestinationRow["B"] = match.SourceRow["B"];
            match.DestinationRow["C"] = true;
        }

        Console.WriteLine("After...");
        Console.WriteLine(PrintTable(table1));
    }

    private static DataTable GetEmptyTable()
    {
        var table = new DataTable();
        table.Columns.Add("A", typeof(int));
        table.Columns.Add("B", typeof(string));
        table.Columns.Add("C", typeof(bool));
        return table;
    }

    private static string PrintTable(DataTable table)
    {
        return string.Join(Environment.NewLine, table.Select().Select(x => "[" + 
string.Join(", ", x.ItemArray) + "]"));
    }
}

【讨论】:

  • 谢谢 Tyler,我想我明白了。我现在有下面的代码,但即使我知道它应该(在 MSSQL 中测试)它也没有返回任何东西。 “src”中的一行具有值为 10 的 ITMREF,而“lookup”中的一行具有值为 10 的 BillingCode。这两个列都是 varchar / string。 var error_rows = sage_invoices.Select() .Join(sage_billing_conversion.Select(), src => sage_invoices.Columns["ITMREF"], lookup => sage_billing_conversion.Columns["BillingCode"], (src, lookup) => new { DestinationRow = src, SourceRow = 查找 });
  • 看起来您的键选择器函数正在使用 sage_invoicessage_billing_conversion,而它们应该使用 srclookupsrclookup 是单独的 DataRow 实例,因此您实际上提供了一个映射函数来检索每个 DataRow 的键值。 sage_invoices.Columnssage_billing_conversion.Columns 返回一个 DataColumn 实例(不是实际值),这两个表之间永远不会匹配。
  • 天啊...我显然需要咖啡。谢谢泰勒 - 明白了。你是个传奇!
  • 太棒了!很高兴我能帮上忙。
猜你喜欢
  • 1970-01-01
  • 2015-05-16
  • 1970-01-01
  • 1970-01-01
  • 2020-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多