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

如何在EF查询中排除<User,User>重复对并转为List<User>?

解决方法

核心问题是当前的Distinct()因为匿名对象中用户顺序不同就判定为不同实例,所以要先统一每对用户的排序规则,让顺序相反的配对变成完全一致的结构,再做去重,最后提取所有无重复的用户。

1. 统一配对顺序,过滤重复配对

修改查询逻辑,在Select时基于用户唯一标识(比如Id)调整顺序,把ID更小的用户放在前面,这样原本顺序相反的配对会变成完全相同的匿名对象,Distinct()就能正确过滤重复项:

var uniquePairs = _db.Messages
    .Where(p => p.UserId == parameters.UserId || p.ToUserId == parameters.UserId)
    .Select(p => new 
    {
        First = p.FirstUser.Id < p.SecondUser.Id ? p.FirstUser : p.SecondUser,
        Second = p.FirstUser.Id < p.SecondUser.Id ? p.SecondUser : p.FirstUser
    })
    .Distinct();

2. 提取并去重所有用户

从去重后的配对中,把两个用户合并成一个集合,再做一次去重得到最终的List<User>:

// 如果User类已正确实现IEquatable<User>或重写了Equals/GetHashCode
var uniqueUsers = uniquePairs
    .SelectMany(pair => new[] { pair.First, pair.Second })
    .Distinct()
    .ToList();

// 如果User类未实现相等比较,可按ID去重
var uniqueUsers = uniquePairs
    .SelectMany(pair => new[] { pair.First, pair.Second })
    .GroupBy(u => u.Id)
    .Select(g => g.First())
    .ToList();

合并为单查询(可选)

也可以把两步合并成一个EF查询,避免提前将数据拉取到内存:

var uniqueUsers = _db.Messages
    .Where(p => p.UserId == parameters.UserId || p.ToUserId == parameters.UserId)
    .Select(p => new 
    {
        First = p.FirstUser.Id < p.SecondUser.Id ? p.FirstUser : p.SecondUser,
        Second = p.FirstUser.Id < p.SecondUser.Id ? p.SecondUser : p.FirstUser
    })
    .Distinct()
    .SelectMany(pair => new[] { pair.First, pair.Second })
    .Distinct()
    .ToList();

注意事项

  • 必须用用户的唯一标识(比如Id)来排序配对,确保顺序相反的配对能被识别为重复。
  • 若要让EF将Distinct()正确转换为SQL语句,User类需要正确实现相等比较逻辑,或者在查询中明确基于唯一标识分组去重。

内容的提问来源于stack exchange,提问作者FX_Sektor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 11:50:21