linq C# -两个数据表比较,获取更新、删除和创建的行(新建)

wfypjpf4  于 2022-12-15  发布在  C#
关注(0)|答案(2)|浏览(296)

我有2个数据表:今天创建了第一个数据表,昨天创建了第二个数据表。每个数据表包含超过100 K行和30列。我有一个唯一的列-“Master_ID”
我希望进行比较和减法(今天的数据表-昨天的数据表),并获取更新、删除和新建的行。我希望执行完整的逐行比较。
输出-〉字典〈字符串,列表数据行〉
1.字典〈“新数据行”,列表数据行〉
1.字典〈“更新的数据行”,列表数据行〉
1.字典〈“删除的数据行”,列出数据行〉
我正在寻找一种高效的方法,可能使用LINQ。

zwghvu4y

zwghvu4y1#

最有效的方法之一可能是使用类似字典的集合来确定行标识符是否是新的,我会使用ILookup<TKey, TValue>

public static Dictionary<string, List<DataRow>?> GetChanges(DataTable dtNew, DataTable dtOld, string masterKeyName, StringComparer masterKeyComparer = null)
{
    IEqualityComparer<string> comparer = masterKeyComparer ?? StringComparer.Ordinal;
    ILookup<string, DataRow> newKeyLookup = dtNew.AsEnumerable().ToLookup(r => r.Field<string>(masterKeyName), comparer!)!;
    ILookup<string, DataRow> oldKeyLookup = dtOld.AsEnumerable().ToLookup(r => r.Field<string>(masterKeyName), comparer!)!;
    List<DataRow> updatedRows = new();
    List<DataRow> newRows = new();
    List<DataRow> deletedRows = new();

     foreach (var x in newKeyLookup)
     {
        List<DataRow> existingRows = oldKeyLookup[x.Key].ToList();
        if (existingRows.Any())
        {
            // potential update, check if there are changes:
            var allChangedRows = x.Where(r => !existingRows.Contains(r, DataRowComparer.Default));
            updatedRows.AddRange(allChangedRows);
        }
        if (!existingRows.Any())
        {
            newRows.AddRange(x);
        }
    }

    foreach (var x in oldKeyLookup)
    {
        if (!newKeyLookup[x.Key].Any())
        {
            deletedRows.AddRange(x);
        }
    }

    return new Dictionary<string, List<DataRow>?>
    {
        {"New Data Rows", newRows},
        {"Updated Data Rows", updatedRows},
        {"Deleted  Data Rows", deletedRows},
    };
}
hmmo2u0o

hmmo2u0o2#

这段代码可能会对你有所帮助。它获取新DataTable中的每一行,并在旧DataTable中查找它(以获取创建和更新的行),然后获取旧表中所有在新表中找不到的行(以获取删除的行)。如果你的表包含超过100K行,它会运行得非常慢,所以你最好把它放在一个单独的线程中。

如果Master_ID列相同,我的代码会将两个不同的行视为一个更新行。

DataTable oldTable, newTable; // Put there your tables
Dictionary<int, DataRow> deletedRows, newRows = new Dictionary<int, DataRow>(); // Here will be the result (key — row's Master_ID, value — the row)
var updatedRows = new Dictionary<int, Tuple<DataRow, DataRow>>(); // Here will be the result (key — row's Master_ID, value — tuple (first item — old row version, second item — new row version))

var commonIds = new List<int>();

foreach (var row in newTable.Rows) {
  var id = row["Master_ID"];

  if (oldTable.Contains(id)) {
    commonIds.Add((int)id);

    var rowInOldTable = oldTable.Rows.Find(id);

    foreach (var column in oldTable.Columns) {
      if (row[column] != rowInOldTable[column]) {
        updatedRows.Add((int)id, Tuple.Create<DataRow, DataRow>(rowInOldTable, row));
        break;
      }
    }
  } else {
    newRows.Add((int)id, row);
  }
}

deletedRows = (from row in oldTable.Rows
               where !commonIds.Contains((int)row["Master_ID"]))
              .ToDictionary<DataRow, int>(row => (int)row["Master_ID"]);

相关问题