LINQ to Entites: подсчет отношений один-ко-многим - PullRequest
0 голосов
/ 20 апреля 2010

У меня есть пара таблиц, где есть отношения один ко многим.Допустим, у меня есть таблица Country, таблица State с FK для Country и таблица City с FK для State.

Я хотел бы иметь возможность создать счетчик всех городов для данногострана, а также количество городов на основе фильтра - что-то вроде:

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 ]

1 голос
/ 20 апреля 2010

Вы можете попробовать, предполагая, что у вас уже есть заданная переменная переменнаяCountry и значение:

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

Выше вы берете весь свой набор городов (EntityMode.CitySet). Этот набор содержит все города во всех штатах во всех странах. Возникает проблема: какое подмножество этих городов находится в стране «данной стране»? Чтобы выяснить это, вы применяете Where () ко всему набору и сравниваете идентификаторы стран, чтобы увидеть, совпадают ли они. Однако, поскольку город знает только, в каком штате он находится (а не в стране), сначала необходимо указать его состояние (it.State). it.State ссылается на объект состояния, и этот объект имеет свойство Country, которое будет ссылаться на страну. Затем it.State.Country ссылается на страну, в которой он находится, а it - город, создавая связь между городом и страной.

Обратите внимание, что вы могли бы сделать это наоборот также с

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

Что касается количества городов с определенным полем, вы применяете аналогичный подход с вызовом Where ():

int filtered = EntityModel.CitySet.Where( it => it.field == value ).Count();
0 голосов
/ 20 апреля 2010

Почему бы вам не отменить это?

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();
}
0 голосов
/ 20 апреля 2010

Вы должны явно загружать дочерние элементы в Entity Framework. Если вы загрузите всех детей, вы можете получить счет просто отлично.

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

Предполагая, конечно, что итерация по всем странам важна. В противном случае, почему бы просто не выполнить запрос по городу, отфильтрованному по штату и стране?

В вашем штате foreach вы просто должны уметь

tot += state.City.Where(x=> x.Field == value).Count();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...