比较两个数据集 - 查找变化 - LINQ

9
我已经在互联网上搜索了很久,试图找到一个解决方案,也许我的方法不对。
我需要比较两个相同结构的数据集,并希望使用LINQ查找新对象和更改的对象。
使用我在CodeProject中找到的内容,我能够汇总出一份已更改项目的列表,但这是通过硬编码每个列(而且会有很多)并检查相同的值来完成的。
var updRec = from u in updated
             join o in orig
                on u.KeyValue equals o.KeyValue
             where
                (o.Propery1 != u.Propery1) ||
                (o.Propery2 != u.Propery2)
             select new record
             {
                 KeyValue = u.KeyValue,
                 Propery1 = u.Propery1,
                 Propery2 = u.Propery2 ,
                 RecordType = "mod" // Modified
             };

我需要帮助解决两个问题:
  1. 是否有更高效的方法循环遍历每一列,因为我计划添加许多需要比较的属性?必须有更好的方法动态检查两个相同的数据集是否有更改。
  2. 如何查看哪个属性已更改?例如,创建一个“属性,原始值,更新值”列表,其中包含所有不相同的项目?
希望这样解释清楚了。如果我没有正确处理此场景,请随时指出其他处理方式。

你可以在你的 record 对象中重写 Equals() 方法并在那里进行比较。然后你可以将你的 where 子句更改为 where o.Equals(u)。但这只是将比较移动到一个更封装的地方。如果你想要更多的自动化,你可能需要使用反射。 - Daniel Gabriel
你可能需要列出所有的列,也许我不知道更好的方法,但我知道在TSQL中,你必须列出所有的列来比较增量,尽管有一些groupby技巧可以加快比较速度。 - Brian Ogden
你如何定义一个变化?我最近遇到了类似的问题,我创建了一个方法,它将同一类型的两个对象组合起来,从具有非空或默认属性的对象中取值,并提供选择优先级对象的选项,以防两个属性都有值。如果你需要这种方法,请告诉我,我会发帖回答并附上代码和更好的解释。 - Marko Gresak
2个回答

1
您可以使用LINQ Except() 扩展方法。它返回列表中除第二个列表中的内容之外的所有内容。
var orignalContacts = GetOrignal();
var updatedContacts = GetUpdated();

var changedAndNew = updatedContacts.Except(orignalContacts);
var unchanged     = orignalContacts.Except(updatedContacts);

根据您的数据提供程序,您可能需要覆盖对象上的Equals()和GetHashCode()方法。


0
  1. 如果您希望在添加新属性后能够更快,但需要维护代码,则可以编写自定义比较器并使用您的方法。
  2. 如果您想要更慢,可以使用反射动态地遍历所有属性并进行比较:

    IDictionary<string, Tuple<object, object>> GetDifferentProperties<T>(T keyValue1, T keyValue2)
    {
       var diff = new Dictionary<string, object>();
       foreach (var prop in typeof(T).GetProperties(BindingFlags.Public))
       {
          var prop1Value = prop.GetValue(keyvalue1);
          var prop2Value = prop.GetValue(keyValue2);
          if (prop1Value != prop2Value)
            diff.Add(prop.Name, Tuple.Create(prop1Value, prop2Value));
       }
       return diff;
    }
    

然后在你的代码中

    var = results = (from u in updated
                    join o in orig
                    select new
                    {
                       Value1 = o.KeyValue,
                       Value2 = u.KeyValue
                    }).ToArray()
                    .Select(x => GetDifferentProperties(x.Value1, x.Value2))
                    .Select(DoSomestufWithDifference);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接