2010-04-20 27 views
0

我有几个表,其中有一对多的关系。假设我有一个国家表格,一个FK到国家的州表格和一个FK到州表格的城市表格。LINQ到Entites:做一对多关系计数

我希望能够创造出所有城市的数量对于给定的国家,也是基于过滤城市的数 - 是这样的:

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()); 

回答

1

你可以试一下,假设你已经拥有了givenCountry和填充值变量:

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

上面,你把你的整个组城市(EntityMode.CitySet)。这个集合包含所有国家所有州的所有城市。问题就变成了:这些城市的哪个子集在'countryCountry'的国家?要弄明白,你将Where()应用于整个集合,并且比较国家id以查看它们是否相同。然而,由于这个城市只知道它处于哪个国家(而不是国家),所以你首先必须引用它的状态(it.State)。它引用状态对象,并且该对象具有将引用该国家的国家/地区属性。然后它。国家。国家引用国家“它”在和“它”是城市,在城市和国家之间建立联系。

注意,你可以这样做是

int total = givenCountry.Sum(c => c.States.Sum(s.Cities.Count())) 

但是反转为好,在这里你将不得不确保givenCountry有其国集加载到内存中,也即每个国家都有其城市收集加载。这是因为您在加载的对象上使用Linq-to-Entities,而不是在第一个示例中的Entity Framework实例对象上。有一种方法,以工艺的最后一个查询使用,但是实体框架对象:

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

至于城市与特定字段中的数字,你采取了类似的方法用在哪里()调用:

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

问题是linq到实体不能这样工作。我的模型是一个国家集合,一个国家没有城市财产 - 它有一个国家集合,并且每个州都有一个城市集合。 – chris 2010-04-20 13:04:58

+0

如果一个国家拥有一个国家集合,然后相互对立,那么该国就有一个它所隶属的国家。各州和城市也是如此。所以,这意味着从一个城市,你可以到达国家,然后到达国家。当然,这是假设您正在使用实体框架,并且您正在使用实体关系(从数据库中的外键或从模型查看器手动构建)。如果您手动或从其他模型提供者构建了国家/州/城市对象,则该关系将取决于您需要向我们提供的那些模型。 – ADB 2010-04-20 13:35:24

+0

使用EF和asp.net MVC 1.0。模型包含IEnemurable ,并且有关系。解决方案的问题在于国家没有城市导航属性 - 只是国家的集合。 – chris 2010-04-20 13:52:35

0

你必须在实体框架明确加载孩子。如果你加载所有的孩子,那么你可以得到很好的计数。

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

当然假设通过所有国家的迭代是重要的。否则,为什么不只是针对由州和国家过滤的城市进行查询?

在你的国家的foreach你应该能够做到

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

我的模型加载了所有对象 - 我正在遍历它们并显示详细信息,但我想要一些统计信息(“4/7城市..”)类型的东西。 – chris 2010-04-20 12:50:44

+0

如果它完全加载,只是嵌套你的循环,迭代通过每个状态,而不是做state.All() – 2010-04-20 12:52:20

+0

我刚更新我的问题,以显示如何迭代工作。虽然这看起来相当不雅。 – chris 2010-04-20 13:12:54

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(); 
}