LINQ to Entity: использование «Содержит» в выбранной части вызывает непредвиденную ошибку

У меня есть запрос LINQ к объекту Entity Framework. Вот краткое изложение запроса:

//a list of my allies
List<int> allianceMembers = new List<int>() { 1,5,10 };

//query for fleets in my area, including any allies (and mark them as such)
var fleets = from af in FleetSource
             select new Fleet 
             {
                 fleetID = af.fleetID,
                 fleetName = af.fleetName,
                 isAllied = (allianceMembers.Contains(af.userID) ? true : false)
             };

По сути, я собираю набор флотов. Список AllianceMembers содержит INT всех пользователей, которые являются моими союзниками. Я хочу установить isAllied = true, если владелец флота является частью этого списка, и false в противном случае.

Когда я это делаю, я вижу исключение: «LINQ to Entities не распознает метод «Булев метод содержит (Int32)»»

Я могу понять получение этой ошибки, если бы я использовал содержимое в части запроса, но почему я получил бы ее в выборе? К этому моменту я бы предположил, что запрос будет выполнен и вернет результаты. Этот небольшой код вообще никак не ограничивает мои данные.

Любые советы о том, как еще я могу выполнить то, что мне нужно, установив флаг isAllied?

Спасибо


person bugfixr    schedule 29.04.2009    source источник
comment
Следует отметить, что Contains будет поддерживаться в следующей версии Entity Framework.   -  person BlueRaja - Danny Pflughoeft    schedule 25.03.2010


Ответы (4)


var fleets = from af in FleetSource;

var x = from u in fleets.ToList()
                         select new Fleet
                         {
                            fleetID = u.fleetID,
                            fleetName = u.fleetName,
                            isAllied = (allianceMembers.Contains(u.userID) ? true : false)
                         }

вызов ToList() на флотах запрос выполняется, позже вы можете использовать Contains().

person pomarc    schedule 29.04.2009
comment
Не будет ли это перетаскивать все объекты в память, в то время как работающий способ заставить исходный запрос работать не будет перетаскивать объекты AllianceMembers? - person Lasse V. Karlsen; 27.04.2010

Это взято из предыдущего ответа...

Содержит не поддерживается.

IN и JOIN не являются одним и тем же оператором (фильтрация по IN никогда не меняет мощность запроса).

Вместо этого используйте метод соединения. Это несколько сложно понять без использования операторов запроса, но как только вы это сделаете, вы это сделаете.

var foo = 
model.entitySet.Join(  //Start the join
values, //Join to the list of strings
e => e.Name, // on entity.Name
value => value, //equal to the string
(ModelItem ent, String str) => ent);//select the entity

Здесь он использует операторы запроса

var foo = from e in model.entitySet
join val in values on
e.Name equals val
select e;
person miPwn    schedule 29.04.2009
comment
Объединение в моем случае не имеет смысла. Было бы так, если бы я пытался как-то ограничить свои данные, но я этого не делаю. Содержит происходит в выбранной части. - person bugfixr; 29.04.2009

По сути, структура сущностей пытается преобразовать ваш запрос LINQ в оператор SQL, но не знает, как обрабатывать Contains.

Вместо этого вы можете получить свои флоты из базы данных и установить свойство isAllied позже:

var fleets = (from af in FleetSource
              select new Fleet 
              {
                  fleetID = af.fleetID,
                  fleetName = af.fleetName,
                  userId = af.userId
              }).AsEnumerable();

foreach (var fleet in fleets)
{
    fleet.isAllied = (allianceMembers.Contains(fleet.userID) ? true : false);
}
person Ronald Wildenberg    schedule 29.04.2009

Все выше меня не правы!!! (Без обид...) Это не работает, потому что вы используете перегрузку IList «Содержит», а не перегрузку IEnumerable «Содержит». Просто измените на:

allianceMembers.Contains<int>(af.userID)

Добавляя <int>, вы говорите компилятору использовать перегрузку IEnumerable вместо перегрузки IList.

person Lewis    schedule 24.06.2010