EF Core Linq查询中移除Versions字段重复项的解决方案咨询
解决EF Core查询中Versions字段的重复版本问题
看起来你遇到的核心问题是自定义类的Distinct()默认不生效——因为myVersion是引用类型,默认的Distinct会比较对象的引用地址,而你每次new myVersion()都会生成新对象,哪怕属性值完全一样,引用也不同,所以它不会被判定为重复项。下面给你几种可行的解决方法:
方法1:在内存中通过GroupBy先去重(最直接)
不需要修改类结构,直接在生成Versions列表时,先按Version分组,只保留每个版本的第一个条目(你也可以根据需求调整保留规则,比如取最新的Uri):
return data .GroupBy(x => x.Id) .OrderBy(x => x.Key) .Select(g => new myModel { Id = g.Key, Uri = g.Select(x => x.Uri).First(), Code = g.Select(x => x.Code).First(), myVersion = g.Select(x => new myVersion { Version = x.Version, Uri = x.Uri }) .OrderByDescending(x => x.Version) .First(), Versions = g.Select(x => new myVersion { Version = x.Version, Uri = x.Uri }) // 按Version分组,去重相同版本 .GroupBy(v => v.Version) // 取每个版本的第一个条目,也可以改成OrderBy/ThenBy后取特定项 .Select(gv => gv.First()) .OrderByDescending(v => v.Version) .ToList() });
如果你的“重复”定义是**Version和Uri都完全相同**,只需要把GroupBy(v => v.Version)改成GroupBy(v => new { v.Version, v.Uri })即可。
方法2:给myVersion实现相等性接口(让Distinct()生效)
如果你想让Distinct()直接工作,需要让myVersion类实现IEquatable<myVersion>接口,明确告诉.NET怎么判断两个myVersion对象是相等的:
public class myVersion : IEquatable<myVersion> { public string Version { get; set; } public string Uri { get; set; } // 定义相等规则:这里以Version相同为重复依据,你可以根据需求调整 public bool Equals(myVersion other) { if (other is null) return false; return Version == other.Version; // 如果需要Version+Uri都相同才算重复,就改成: // return Version == other.Version && Uri == other.Uri; } // 重写基类的Equals方法,保持一致性 public override bool Equals(object obj) => Equals(obj as myVersion); // 重写GetHashCode,和Equals规则对应 public override int GetHashCode() { return Version?.GetHashCode() ?? 0; // 如果是Version+Uri的规则,改成: // return HashCode.Combine(Version, Uri); } }
之后你原来的Distinct()就可以正常工作了:
Versions = g.Select(x => new myVersion { Version = x.Version, Uri = x.Uri }) .Distinct() .OrderByDescending(x => x.Version) .ToList()
方法3:在数据库层面提前去重(性能最优)
如果你的数据量较大,建议在EF Core查询阶段就去重,避免把重复数据读到内存中,提升性能:
// 先在数据库层按Id+Version分组,拿到去重后的数据 var dbQuery = db.ManifestTable .GroupBy(x => new { x.Id, x.Version }) .Select(g => new { g.Key.Id, g.Key.Version, Uri = g.Select(x => x.Uri).First(), Code = g.Select(x => x.Code).First() }); var data = await dbQuery.ToListAsync(); // 后续的分组和投影就不需要再处理重复了 return data .GroupBy(x => x.Id) .OrderBy(x => x.Key) .Select(g => new myModel { Id = g.Key, Uri = g.Select(x => x.Uri).First(), Code = g.Select(x => x.Code).First(), myVersion = g.Select(x => new myVersion { Version = x.Version, Uri = x.Uri }) .OrderByDescending(x => x.Version) .First(), Versions = g.Select(x => new myVersion { Version = x.Version, Uri = x.Uri }) .OrderByDescending(x => x.Version) .ToList() });
这样数据库返回的就是已经去重后的结果,内存处理阶段就不会有重复项了。
内容的提问来源于stack exchange,提问作者user16267434
相关产品推荐
相关产品推荐

