You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 19:43:12