如何在 C# 中 Update/Merge 两个具有数百个属性的巨大列表 <Class>,以最有效的方式基于公共匹配键
How to Update/Merge two huge List<Class> with hundreds of properties in C#, based on common matching Key in most efficient way
我有两大系列 List<Class>
,其中有数百个属性。
例如原始合集 List<OriginalCollection>
和更新合集 List<UpdatedColleciton>
UpdatedCollection
将包含某些列中的值,这些列很可能不会成为 OriginalCollection
的一部分,并且 UpdatedCollection
可能具有某些 KeyColumn [ID Column] 可能不是 OriginalCollection
的一部分,我在 OriginalCollection
中收到了数千个数据集,并且 UpdatedColletion
的记录会在一段时间内增加。
我确实有一个要求,只有 OriginalCollection
的 null 或空列应该被 ID 匹配的 UpdatedCollection
值替换,如果没有匹配的 ID可用,那么这些记录应该从 UpdatedCollection
.
添加到 OriginalCollection
我尝试使用 AutoMapper
,我尝试根据匹配 ID 使用 UpdatedCollection
更新 OriginalCollection
,但我找不到任何 AutoMapper configuration
我的上述要求。
我正在寻找不应该影响性能的最有效的解决方案,这就是为什么我没有采用典型的并集和交集方式,因为 Modal 有数百个 属性 并且有数千条记录,因为我确实有很多属性,所以我认为像 AutoMapper
这样的库比在循环中编写逻辑来检查所有数千条记录的每一列的值更好。
请提出任何更好且性能高效的解决方案,例如 AutoMapper Configuration 或任何其他 .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);
但它有以下行为,无法按我的要求正常工作
- 如果 ID 匹配会将 OrderDTO 映射到 Order
- 如果 OrderDTO 存在并且订单没有添加到集合中不适合我
- 如果订单存在并且 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;
}
我有两大系列 List<Class>
,其中有数百个属性。
例如原始合集 List<OriginalCollection>
和更新合集 List<UpdatedColleciton>
UpdatedCollection
将包含某些列中的值,这些列很可能不会成为 OriginalCollection
的一部分,并且 UpdatedCollection
可能具有某些 KeyColumn [ID Column] 可能不是 OriginalCollection
的一部分,我在 OriginalCollection
中收到了数千个数据集,并且 UpdatedColletion
的记录会在一段时间内增加。
我确实有一个要求,只有 OriginalCollection
的 null 或空列应该被 ID 匹配的 UpdatedCollection
值替换,如果没有匹配的 ID可用,那么这些记录应该从 UpdatedCollection
.
OriginalCollection
我尝试使用 AutoMapper
,我尝试根据匹配 ID 使用 UpdatedCollection
更新 OriginalCollection
,但我找不到任何 AutoMapper configuration
我的上述要求。
我正在寻找不应该影响性能的最有效的解决方案,这就是为什么我没有采用典型的并集和交集方式,因为 Modal 有数百个 属性 并且有数千条记录,因为我确实有很多属性,所以我认为像 AutoMapper
这样的库比在循环中编写逻辑来检查所有数千条记录的每一列的值更好。
请提出任何更好且性能高效的解决方案,例如 AutoMapper Configuration 或任何其他 .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);
但它有以下行为,无法按我的要求正常工作
- 如果 ID 匹配会将 OrderDTO 映射到 Order
- 如果 OrderDTO 存在并且订单没有添加到集合中不适合我
- 如果订单存在并且 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;
}