2017-02-28 190 views
0

以下查询返回第二个select查询中的重复结果。Linq查询返回重复结果

国家有0..1 to *与联赛的关系。

联盟有1 to *与userLeagues的关系。

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没有运气。 看来,无论是我必须使用不同的或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", 
     } 
    ] 
    } 
] 
+0

也许尝试加入'.ToList()'你要指定为'leagues'查询结束。但是,“重复”是什么意思?你是说每个国家都得到所有的用户联盟,或者每个国家都获得属于最后一个国家的所有用户联盟,或者是什么? –

+0

重复在哪些列/属性? –

+0

你不能使用group by来删除重复的结果吗? –

回答

2

你需要它组由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, 
       }) 
      }; 
1

想想你在做什么:对于每一个联赛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<T>,只写一个快速的相等比较和使用:

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,这可能是一个更可敬的方法来做到这一点。但有人在我做之前就想到了这一点,所以他赢得了荣誉。

0

我会说你需要扭转你的查询。因此,不要从用户联盟开始,而应从国家开始并包含儿童联赛。