LINQ to Entity: usando Contém na parte “select” lança erro inesperado
-
03-07-2019 - |
Pergunta
Eu tenho uma consulta LINQ indo contra um objeto Entity Framework. Aqui está um resumo da consulta:
//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)
};
Basicamente, o que eu estou fazendo é a obtenção de um conjunto de frotas. A lista allianceMembers contém INTs de todos os usuários que estão aliados com mim. Eu quero definir isAllied = true se o proprietário da frota faz parte dessa lista, e falso caso contrário.
Quando eu fizer isso, eu estou vendo uma exceção: "LINQ to Entities não reconhece o método 'booleano Contém (Int32)' método"
Eu posso entender recebendo este erro se eu tivesse usado o contém, no qual parte da consulta, mas por que eu iria buscá-la na seleção? Por este ponto eu diria que a consulta teria executado e retornou os resultados. Esta pequena cantiga de código não faz nada para restringir os meus dados em tudo.
Todas as dicas sobre como mais posso fazer o que eu preciso com definindo o sinalizador isAllied?
Graças
Solução
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)
}
chamando ToList()
em frotas a consulta é executada, mais tarde você pode usar Contains()
.
Outras dicas
Esta escalfado de uma resposta anterior ...
Não Contém suportado.
IN e JOIN não são o mesmo operador (Filtragem pela IN nunca muda a cardinalidade da consulta).
Em vez de fazê-lo dessa maneira usar o método join. É um pouco difícil de entender sem usar os operadores de consulta, mas uma vez que você obtê-lo, você tem isso.
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
Aqui está usando os operadores de consulta ??p>
var foo = from e in model.entitySet
join val in values on
e.Name equals val
select e;
Basicamente as tentativas Entity Framework para traduzir sua consulta LINQ em uma instrução SQL, mas não sabe como lidar com a Contains
.
O que você pode fazer em vez disso é recuperar suas frotas do banco de dados e defina a propriedade isAllied depois:
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);
}
Todos acima de mim está errado !!! (Sem ofensa ...) ele não funciona porque você está usando a sobrecarga IList de "Contém" e não a sobrecarga IEnumerable de "Contém". Basta mudar para:
allianceMembers.Contains<int>(af.userID)
Ao adicionar o <int>
, você está dizendo ao compilador para usar o IEnumerable sobrecarregar vez da sobrecarga de IList.