C# Linq查询:选择全部列并重命名重复列
Linq连接表时重复列的通用重命名方案
Linq原生语法里没有直接实现“全选两表所有字段并自动重命名重复项”的功能——你当前的查询select entry只能返回Utenti实体,自然会丢失AnagraficaUtenti的重复列。不过可以通过以下两种通用方式避免逐个手写字段:
方案一:用反射动态合并字段(返回动态类型)
写一个通用的扩展方法,通过反射读取两个实体的所有属性,给重复属性名加上表前缀后合并到动态对象中:
public static dynamic MergeEntitiesWithPrefix<T1, T2>(T1 entity1, string prefix1, T2 entity2, string prefix2) { var expandoDict = (IDictionary<string, object>)new ExpandoObject(); // 添加第一个实体的所有属性,附带指定前缀 foreach (var prop in typeof(T1).GetProperties()) { expandoDict[$"{prefix1}{prop.Name}"] = prop.GetValue(entity1); } // 添加第二个实体的所有属性,附带指定前缀 foreach (var prop in typeof(T2).GetProperties()) { expandoDict[$"{prefix2}{prop.Name}"] = prop.GetValue(entity2); } return expandoDict; }
然后修改你的查询,直接调用这个方法合并两个实体:
var list = ( from au in context.AnagraficaUtenti join ut in context.Utenti on au.CodiceUtente equals ut.CodiceUtente select MergeEntitiesWithPrefix(au, "AnagraficaUtenti", ut, "Utenti") ) .AsEnumerable() // 注意:EF无法将反射逻辑转换为SQL,需要先拉取数据到内存处理 .ToList();
优缺点
- 优势:完全不用手写字段,适配任意两个实体的合并
- 劣势:返回动态类型,编译时没有类型检查,大数据量下内存处理性能受限
方案二:用DTO+映射工具实现强类型合并
如果需要强类型的结果,先定义包含所有字段的DTO类,重命名重复列:
public class UtenteAnagraficaCombinedDto { // AnagraficaUtenti的字段 public int CodiceUtente { get; set; } public string NameAnagraficaUtenti { get; set; } public string SurnameAnagraficaUtenti { get; set; } // 其他AnagraficaUtenti字段... // Utenti的字段 public string NameUtenti { get; set; } public string SurnameUtenti { get; set; } // 其他Utenti字段... }
然后用AutoMapper配置映射规则(只需配置一次重复字段,其他同名字段可自动映射):
var mapperConfig = new MapperConfiguration(cfg => { cfg.CreateMap<(AnagraficaUtenti Au, Utenti Ut), UtenteAnagraficaCombinedDto>() .ForMember(dest => dest.NameAnagraficaUtenti, opt => opt.MapFrom(src => src.Au.Name)) .ForMember(dest => dest.SurnameAnagraficaUtenti, opt => opt.MapFrom(src => src.Au.Surname)) .ForMember(dest => dest.NameUtenti, opt => opt.MapFrom(src => src.Ut.Name)) .ForMember(dest => dest.SurnameUtenti, opt => opt.MapFrom(src => src.Ut.Surname)); }); var mapper = mapperConfig.CreateMapper();
最后修改查询,先拉取两个实体的匿名对象,再映射到DTO:
var list = ( from au in context.AnagraficaUtenti join ut in context.Utenti on au.CodiceUtente equals ut.CodiceUtente select new { Au = au, Ut = ut } ) .AsEnumerable() .Select(item => mapper.Map<UtenteAnagraficaCombinedDto>(item)) .ToList();
优缺点
- 优势:强类型安全,编译时可检查,性能更稳定
- 劣势:需要提前定义DTO类,第一次配置映射规则
总结
Linq本身没有原生的“全选+自动重命名”语法,但通过反射动态合并或DTO+映射工具,能实现不用逐个手写字段的通用解决方案。
内容的提问来源于stack exchange,提问作者Alessandro
相关产品推荐
相关产品推荐

