79 votes

Entity Framework - erreur "Impossible de créer une valeur constante de type 'Type de fermeture' ... ''

Pourquoi ai-je le message d'erreur " Impossible de créer une valeur constante de type 'Type de fermeture'. Seuls les types primitifs (par exemple, Int32, String et Guid) sont pris en charge dans ce contexte. " Lorsque j'essaie d'énumérer la requête Linq suivante?

 IEnumerable<string> searchList = GetSearchList();
using (HREntities entities = new HREntities())
{
   var myList = from person in entities.vSearchPeople
   where upperSearchList.All( (person.FirstName + person.LastName) .Contains).ToList();
}
 

Mise à jour: Si j'essaye ce qui suit pour essayer d'isoler le problème, j'obtiens la même erreur:

 where upperSearchList.All(arg => arg == arg)
 

On dirait donc que le problème vient de la méthode All, non? Aucune suggestion?

68voto

Daniel Pratt Points 8151

Il semble que vous essayez de faire l'équivalent d'un "OÙ" EN l'état". Découvrez cet article de blog pour un exemple de la façon de faire ce type de requête avec LINQ to entities.

Aussi, je pense que le message d'erreur est particulièrement utile dans ce cas parce que ".Contient" n'est pas suivi par des parenthèses, ce qui provoque le compilateur de reconnaître l'ensemble du prédicat comme une expression lambda.

57voto

Salar Khalilzadeh Points 655

C’est un problème connu: problèmes connus et considérations dans LINQ to Entities

11voto

andrew Points 965

J'ai passé les 6 derniers mois, le combat contre cette limitation avec EF 3.5 et alors que je ne suis pas la personne la plus intelligente dans le monde entier, je suis sûr que j'ai quelque chose d'utile à offrir sur ce sujet.

Le SQL généré par la croissance de 50 mile de haut arbre de la "OU le style" expressions permettront de merde plan d'exécution de requête. Je fais face à quelques millions de lignes et l'impact est considérable.

Il y a un peu de bidouille, j'ai trouvé pour faire un SQL 'dans', qui aide si vous êtes simplement à la recherche d'un groupe d'entités par id:

private IEnumerable<Entity1> getByIds(IEnumerable<int> ids)
{
    string idList = string.Join(",", ids.ToList().ConvertAll<string>(id => id.ToString()).ToArray());
    return dbContext.Entity1.Where("it.pkIDColumn IN {" + idList + "}");
}

où pkIDColumn est votre id de clé primaire nom de la colonne de votre l'entité1 table.

MAIS CONTINUEZ À LIRE!

C'est bien, mais cela nécessite que j'ai déjà eu l'id de ce que j'ai besoin de trouver. Parfois, je veux juste mes expressions à atteindre dans d'autres relations et de ce que j'ai, est des critères pour celles qui sont liées relations.

Si j'avais plus de temps, je voudrais essayer de représenter visuellement, mais je n'ai pas seulement d'étudier cette phrase un moment: Considérons un schéma avec une Personne, GovernmentId, et GovernmentIdType tables. Andrew Tappert (Personne) a deux cartes d'identité (GovernmentId), l'un de l'Oregon (GovernmentIdType) et l'autre de Washington (GovernmentIdType).

Maintenant générer un edmx.

Maintenant, imaginez que vous voulez trouver toutes les personnes qui ont une certaine valeur de l'ID, dire 1234567.

Ceci peut être accompli avec une base de données unique frappé avec cela:

dbContext context = new dbContext();
string idValue = "1234567";
Expression<Func<Person,bool>> expr =
    person => person.GovernmentID.Any(gid => gid.gi_value.Contains(idValue));

IEnumerable<Person> people = context.Person.AsQueryable().Where(expr);

Voyez-vous la sous-requête ici? Le sql généré utilisera 'rejoint' au lieu de sous-requêtes, mais l'effet est le même. Ces journées SQL server optimise les sous-requêtes dans les jointures sous les couvertures, de toute façon, mais de toute façon...

La clé de ce travail est la .Tout l'intérieur de l'expression.

8voto

peter70 Points 92

J'ai trouvé la cause de l'erreur (je suis en utilisant des Framework 4.5). Le problème, c'est que EF un type complexe, qui est passé dans la "Contient"-paramètre, ne peut pas se traduire par une requête SQL. EF pouvez utiliser dans une requête SQL uniquement les types simples tels que int, string...

this.GetAll().Where(p => !assignedFunctions.Contains(p))

GetAll fournit une liste d'objets avec un type complexe (par exemple: "Fonction"). Donc, je voudrais essayer ici pour recevoir un exemple de ce type complexe dans ma requête SQL, qui, naturellement, ne peut pas travailler!

Si je peux tirer de ma liste, les paramètres qui sont adaptés à ma recherche, je peux utiliser:

var idList = assignedFunctions.Select(f => f.FunctionId);
this.GetAll().Where(p => !idList.Contains(p.FunktionId))

Maintenant EF n'a plus le complexe de type "Fonction" pour le travail, mais par exemple avec un type simple (long). Et qui fonctionne très bien!

0voto

ang Points 46

J'ai reçu ce message d'erreur lorsque mon objet tableau utilisé dans la fonction .All est null. Après avoir initialisé l'objet tableau (upperSearchList dans votre cas), l'erreur a disparu. Le message d'erreur était trompeur dans ce cas.

où upperSearchList.All (arg => personne.someproperty.StartsWith (arg)))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X