Linq中如何高效实现内连接并填充对象属性
最简实现方案
你不需要逐属性初始化新对象,也不需要额外拆分Join和遍历赋值两步,直接利用Join方法的结果选择器,就可以在连接阶段直接完成属性赋值,全程只做一次遍历,没有匿名对象的额外开销。
方法语法(最简洁高效)
直接在Join的结果选择器委托里完成Desc赋值,返回原c1实例即可,所有原有属性会完整保留:
IEnumerable<Category> result = categoriesOne.Join( categoriesTwo, c1 => c1.IdCategory, c2 => c2.IdCategory, (c1, c2) => { c1.Desc = c2.Desc; return c1; } );
执行后返回的结果就是你需要的两个匹配到的Category实例,Name、IdCategory以及其他所有原有属性都和categoriesOne里的原实例一致,仅补充了匹配到的Desc值,没有匹配到的Other food项会被内连接逻辑自动过滤。
查询语法版本
如果偏好查询表达式的结构,可以搭配一个极简的辅助方法实现,效果和上面完全一致:
// 辅助方法,仅做属性赋值后返回原对象 static Category FillDesc(Category target, Category source) { target.Desc = source.Desc; return target; } // 查询语法实现内连接+赋值 var result = from c1 in categoriesOne join c2 in categoriesTwo on c1.IdCategory equals c2.IdCategory select FillDesc(c1, c2);
如果你需要做左连接(保留categoriesOne里没有匹配到Desc的项),可以用into分组的写法:
var leftJoinResult = from c1 in categoriesOne join c2 in categoriesTwo on c1.IdCategory equals c2.IdCategory into matchedGroup from matched in matchedGroup.DefaultIfEmpty() select matched != null ? FillDesc(c1, matched) : c1;
方案说明
- 以上写法都不需要手动给IdCategory、Name等大量属性逐一枚举赋值,直接复用
categoriesOne里的原有实例,没有冗余代码。 - 性能比你原来先Join生成匿名对象、再遍历赋值的写法更高,省去了匿名类型实例化的内存和时间开销,时间复杂度和标准内连接一致,为O(n+m)。
- 如果你不希望修改
categoriesOne集合里的原有实例,不建议手动逐属性拷贝,可以引入对象映射库配置仅映射Desc属性,自动完成对象浅拷贝,减少重复代码。
内容的提问来源于stack exchange,提问作者user16276760
相关产品推荐
相关产品推荐

