如何以最有效的方式更新/合并两个具有<Class>数百个属性的 C# 中具有数百个属性的庞大列表



我有两个大型集合List<Class>,其中包含数百个属性。

例如原始馆藏List<OriginalCollection>和更新馆藏List<UpdatedColleciton>

UpdatedCollection将包含某些列中的值,这些列很可能不是OriginalCollection的一部分,并且UpdatedCollection可能具有某些可能不属于OriginalCollection键列[ID列],并且我正在OriginalCollection中接收数千个数据集,并且UpdatedColletion记录将在一段时间内增加。

我确实有一个要求,只有空或空的OriginalCollection列应该被替换为 ID 匹配UpdatedCollection值,如果没有匹配的 ID 可用,那么这些记录应该从 UpdatedCollection OriginalCollection中添加。

我尝试使用 AutoMapper ,我试图根据匹配的 ID 使用UpdatedCollection更新OriginalCollection,为此我找不到上述要求集的任何AutoMapper configuration

我正在寻找不影响性能的最有效的解决方案,这就是为什么我没有抛出典型的联合和交叉方式,因为 Modal 有数百个属性和数千条记录,而且因为我确实有很多属性我认为像AutoMapper这样的库是不错的选择,而不是在循环中编写逻辑来检查所有数千条记录的每一列的值。

请建议任何更好且性能高效的解决方案,例如自动映射器配置或任何其他 .Net 内置功能来实现此方案。

我还从 https://github.com/AutoMapper/AutoMapper.Collection 中检查了以下AutoMapper.Collection

 cfg.CreateMap<OrderItemDTO, OrderItem>().EqualityComparison((odto, o) => odto.ID == o.ID);
 Mapping OrderDTO back to Order will compare Order items list based on if their ID's match
 Mapper.Map<List<OrderDTO>,List<Order>>(orderDtos, orders);

但它有以下行为,并且没有按照我的要求正常工作

  1. 如果 ID 的匹配项将订单DTO映射到订单
  2. 如果 OrderDTO 存在并且 Order 未添加到集合中 对我不起作用
  3. 如果订单存在并且 OrderDTO 未从集合中删除 对我不起作用

AutoMapper是已知的映射库,也有很好的文档,但无法找到类似的详细文档AutoMapper.Collection,我已经探索了AutoMapper.Collection但它没有按照我的要求提供解决方案。

所以,我需要走传统的方式。

通过LINQ查询准备收集差异。

 var common = original.Where(x => revised.Exists(z => z.ID == x.ID)).ToList();
 var nonCommon = revised.Where(x => !original.Exists(z => z.ID == x.ID)).ToList();
 foreach(var item in common)
 {
      var derived = revised.FirstOrDefault(x => x.ID == item.ID);
      // Added Extention Method to compare and update property
      var data = item.UpdateProperties(derived);
 }
 common.AddRange(nonCommon);

利用反射来比较对象,并在属性级别比较后更新其值,适用于所有数据类型。

public static T UpdateProperties<T>(this T source, T destination)
{
    Type type = source.GetType();   // Gets Source Object Type
    PropertyInfo[] props = type.GetProperties();    // Gets Source object Properties
    foreach (var prop in props)     // Iterate threw all properties of source object
    {
        var sourceValue = prop.GetValue(source);    // Get source object value by Property Name
        var destinationValue = prop.GetValue(destination);      // Get destination object value by Property Name, to update source object
        // Update source object property value only if derived object's property has value and source object doesn't
        if (string.IsNullOrEmpty(sourceValue?.ToString()) && !string.IsNullOrEmpty(destinationValue?.ToString()))
        {
            prop.SetValue(source, destinationValue);    // Update source object's property with value of derived object
        }
    }
    return source;
}

最新更新