【问题标题】:Linq query returns duplicate resultsLinq 查询返回重复的结果
【发布时间】:2017-02-28 17:17:45
【问题描述】:

以下查询在第二个选择查询中返回重复的结果。

国家/地区与联赛有0..1 to * 关系。

Leagues 与 userLeagues 有1 to * 关系。

    return from ul in userLeagues
            select new Map.Country
            {
                id = ul.Country.CountryId,
                name = ul.Country.Common_Name,
                leagues =  userLeagues.Where(x => x.CountryId.Value == ul.CountryId.Value)
                                     .Select(x => new Map.League
                                     {
                                         id = x.LeagueID,
                                         name = x.leagueNameEN,
                                     })

            };

我尝试使用Distinct,但没有成功。 看来我必须使用 distinct 或 groupby countryId

输出如

[
  {
    "id": 1,
    "name": "Europe",
    "leagues": [
      {
        "id": 2,
        "name": "Champions League",
      },
      {
        "id": 3,
        "name": "Europa league",
      }
    ]
  },
  {
    "id": 1,
    "name": "Europe",
    "leagues": [
      {
        "id": 2,
        "name": "Champions League",
      },
      {
        "id": 3,
        "name": "Europa league",
      }
    ]
  }
]

【问题讨论】:

  • 也许尝试在您分配给leagues 的查询末尾添加.ToList()。但是你所说的“重复”是什么意思?你是说每个国家都有所有的用户联盟,还是每个国家都有属于最后一个国家的所有用户联盟,还是什么?
  • 在哪些列/属性上重复?
  • 你不能使用 group by 来删除重复的结果吗?
  • @Neel 这似乎是我的大问题。我试过了,但是......
  • 看来您只需将userLeaguesCountry 分组即可。或者从 Country 表开始并使用导航属性或 GroupJoinUserLeagues。一般来说,当您有 EF 相关问题时,您应该提供实体模型类。

标签: c# entity-framework linq


【解决方案1】:

您需要按CountryIdCommon_Name 对其进行分组以获得预期结果:

var result = from ul in userLeagues
             group ul by new { ul.Country.CountryId, ul.Country.Common_Name } into g
             select new Map.Country
             {
                 id = g.Key.CountryId,
                 name = g.Key.Common_Name,
                 leagues = g.Select(x => new Map.League
                 {
                     id = x.LeagueID,
                     name = x.leagueNameEN,
                 })
             };

【讨论】:

    【解决方案2】:

    想想你在做什么:对于userLeagues 中的每个联赛,你正在为该联赛所属的国家/地区创建一个Map.Country。如果三个联赛在法国,那就是三个弗朗西斯。法国是一个很棒的国家,但我们不要过火。

    相反,您希望从不同的国家/地区列表开始。对于每一个,创建一个Map.Country,并给Map.Country 一个应该属于它的联赛列表。

    首先,让Country 实现IEquatable<Country> 用于Distinct 的目的:

    public class Country : IEquatable<Country>
    {
        public bool Equals(Country other)
        {
            return other.CountryID == CountryID;
        }
    

    其次,您希望从不同的国家/地区列表开始,然后用联赛填充它们。

    var q =
        from ctry in userLeagues.Select(ul => ul.Country).Distinct()
        select new
        {
            id = ctry.CountryID,
            name = ctry.Common_Name,
            leagues = userLeagues.Where(x => x.Country == ctry)
                                 .Select(x => new
                                 {
                                     id = x.LeagueID,
                                     name = x.leagueNameEn
                                 }).ToList()
        };
    

    我没有重新创建你的 Map.LeagueMap.Country 类,我只是使用了匿名对象,然后我就这样离开了,因为这段代码确实可以正常工作。但是填写您的班级名称是微不足道的。

    如果让Country 实现IEquatable&lt;T&gt; 不切实际,只需编写一个快速相等比较器并使用它:

    public class CountryComparer : IEqualityComparer<Country>
    {
        public bool Equals(Country x, Country y)
        {
            return x.CountryID == y.CountryID;
        }
    
        public int GetHashCode(Country obj)
        {
            return obj.CountryID.GetHashCode();
        }
    }
    

    ...像这样:

    var cc = new CountryComparer();
    
    var q =
        from ctry in userLeagues.Select(ul => ul.Country).Distinct(cc)
        select new
        {
            id = ctry.CountryID,
            name = ctry.Common_Name,
            leagues = userLeagues.Where(x => cc.Equals(x.Country, ctry))
                                 .Select(x => new
                                 {
                                     id = x.LeagueID,
                                     name = x.leagueNameEn
                                 }).ToList()
        };
    

    这在逻辑上等同于GroupBy,这可能是一种更体面的方式。但在我之前有人想到了这一点,所以他赢得了荣耀。

    【讨论】:

      【解决方案3】:

      我会说您需要反转您的查询。因此,不要从 userLeagues 开始,而是从国家开始并包括子联赛。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-30
        • 1970-01-01
        • 2011-01-19
        • 2015-12-07
        • 1970-01-01
        • 1970-01-01
        • 2010-09-25
        • 1970-01-01
        相关资源
        最近更新 更多