LINQ to Entities:对一对多关系进行计数

时间:2010-04-20 12:40:43

标签: entity-framework linq-to-entities

我有几张桌子,里面有一对多的关系。假设我有一个Country表,一个FK到Country的State表,以及一个带FK to State的City表。

我希望能够为特定国家/地区创建所有城市的统计数据,并根据过滤器计算城市数量 - 例如:

foreach( var country in Model.Country ) {
    total = country.State.All().City.All().Count() ;
    filtered = country.State.All().City.Any(c=>c.field == value).Count();
}

显然,这不起作用 - 有没有办法做到这一点?

更新

我可以通过对象进行迭代:

    foreach (var item in Model ) {

      ... other stuff in here ...

      int tot = 0;
      int filtered = 0;
      foreach (var state in item.State)
      {
        foreach (var city in state.City)
        {
          tot++;
          if (city.Field == somevalue)
            filtered ++;
        }
      }

      ... other stuff in here ...

    }

但这似乎并不优雅。

更新:@AD有一些建议,但解决问题的方法是:

int tot = item.States.Sum(s=>s.City.Count);
int filtered = item.States.Sum(s=>s.City.Where(c=>c.Field == somevalue).Count());

3 个答案:

答案 0 :(得分:1)

您可以尝试,假设您已经填充了givenCountry和value变量:

int total = EntityModel.CitySet.Where( it => it.State.Country.ID == givenCountry.ID ).Count();

在上面,您将获取整个城市集(EntityMode.CitySet)。该集包含所有国家/地区所有州的所有城市。问题变成:这些城市的哪个子集在国家'givenCountry'?为了解决这个问题,您将Where()应用于整个集合,并比较国家/地区ID以查看它们是否相同。但是,由于城市只知道它所在的州(而不是国家),因此首先必须引用其状态(it.State)。 it.State引用状态对象,该对象具有将引用该国家/地区的Country属性。然后it.State.Country引用国家'它'在,'它'是城市,创建城市和国家之间的链接。

请注意,您可以使用

进行反向操作
int total = givenCountry.Sum( c => c.States.Sum( s.Cities.Count() ) )

但是,在这里,您必须确保givenCountry将其States集合加载到内存中,并且每个State都加载了其Cities集合。这是因为您在加载的对象上使用Linq-to-Entities而在第一个示例中没有在Entity Framework实例对象上使用。有一种方法可以设计最后一个查询以使用实体框架对象:

int total = EntityModel.CountrySet.Where( c => c.ID == givenCountry.ID ).Sum( c => c.States.Sum( s.Cities.Count() ) )

对于具有特定字段的城市数量,您采用类似的方法进行Where()调用:

int filtered = EntityModel.CitySet.Where( it => it.field == value ).Count();

答案 1 :(得分:0)

您必须在Entity Framework中显式加载子项。如果你加载所有的孩子,那么你可以得到很好的计数。

IEnumberable<Country> countries = Model.Country.Include("State");
total = countries[i].State.Count();

当然假设所有国家的迭代都很重要。否则,为什么不直接查询按州和国家筛选的城市?

在你的州,你应该能够做到

tot += state.City.Where(x=> x.Field == value).Count();

答案 2 :(得分:0)

为什么不扭转呢?

foreach( var country in Model.Country ) {
    var city  = Model.State.Where(x=>x.StateID==country.State.StateID).Select(x=>City)
    total  = city.Count();
    filtered = city.All(c=>c.field == value).Count();
}