72 votes

"Le type de noeud d'expression LINQ 'Invoke' n'est pas pris en charge dans LINQ to Entities" - stumped!

Plus tard, dans mon EF, j'essaie de transmettre une fonction anonyme à utiliser dans le cadre de ma requête Linq. La fonction passerait dans un INT et renverrait un BOOL (u.RelationTypeId est un INT). Ci-dessous une version simplifiée de ma fonction:

 public IEnumerable<UserBandRelation> GetBandRelationsByUser(Func<int, bool> relation)
{
    using (var ctx = new OpenGroovesEntities())
    {
        Expression<Func<UsersBand, bool>> predicate = (u) => relation(u.RelationTypeId);

        var relations = ctx.UsersBands.Where(predicate);

        // mapping, other stuff, back to business layer
        return relations.ToList();
    }
}
 

Cependant, j'obtiens l'erreur mentionnée ci-dessus. Il semble que tout se passe bien en construisant un prédicat à partir de la fonction. Des idées? Merci.

124voto

Leniel Macaferi Points 38324

J'ai été faire cette erreur et je suis en utilisant Entity Framework avec PredicateBuilder par Joe Albahari de construire des dynamiques where clauses. Si vous arrive d'être dans le même état, vous devez appeler l' AsExpandable méthode:

Si l'interrogation avec Entity Framework, modifier la dernière ligne de ce:

return objectContext.Products.AsExpandable().Where(predicate);

Cette méthode fait partie de LINQKIT DLL que vous pouvez récupérer ici ou par le biais d'un package NuGet ici.

Tout fonctionne bien maintenant. :)

52voto

Jon Skeet Points 692016

Vous essayez de passer un arbitraire .NET en fonction... comment pourrait-entity framework espoir pour traduire cela en SQL? Vous pouvez le changer pour prendre un Expression<Func<int, bool>> au lieu de cela, et construire l' Where clause de cela, bien que ce ne sera pas particulièrement facile, car vous aurez besoin de la réécrire avec un paramètre différent de l'expression (c'est à dire le remplacement quel que soit le paramètre expression est dans l'expression d'origine de l'arbre avec l'expression de l'appelant u.RelationTypeId).

Pour être honnête, pour l'amour de seulement la spécification u.RelationTypeId dans l'expression lambda que vous utilisez pour créer l'arborescence d'expression pour passer dans la méthode, vous seriez mieux d'utiliser simplement:

public IEnumerable<UserBandRelation> GetBandRelationsByUser(
    Expression<Func<UsersBand, bool>> predicate)
{
    using (var ctx = new OpenGroovesEntities())
    {
        var relations = ctx.UsersBands.Where(predicate);

        // mapping, other stuff, back to business layer
        return relations.ToList();
    }
}

-1voto

Jim Points 1

Il y a un produit appelé Couche de LINQ qui élimine NotSupportedExceptions en EF comme dans LINQ to SQL, de sorte que votre requête travail. C'est un client de code côté de projection comme ce que LINQ to SQL, de sorte que vous pouvez utiliser n'importe quel code C# dans vos requêtes LINQ to entities.

Toutefois, si un où le prédicat est tout simplement l'appel d'une méthode, la relation() dans cet exemple, la totalité de la clause where exécuter côté client, et il serait assez lente si il y a un grand nombre de données dans UserBands.

www.layeroverlinq.com

-1voto

hossein ab Points 63
  1. ajouter
    using System.Data.Entity;
  2. changez votre code en ci-dessous:

             public IEnumerable<UserBandRelation> GetBandRelationsByUser(Func<int, bool> relation)
            {
                using (var ctx = new OpenGroovesEntities())
                {
                    Expression<Func<UsersBand, bool>> predicate = (u) => relation(u.RelationTypeId);
                    ctx.UsersBands.Load();//*****************************
                    var relations = ctx.UsersBands.Local.Where(predicate);//****
    
                    // mapping, other stuff, back to business layer
                    return relations.ToList();
                }
            }
     

    Remarque: // ******* = lignes modifiées!

-7voto

Yushatak Points 1

Je sais que cette réponse est vraiment en retard, mais j'ai rencontré le même problème et cela m'a conduit ici. J'ai donc pensé partager ma solution.

J'ai lu la réponse de Leniel et cela m'a donné une idée. Les types par défaut ont la méthode "AsEnumerable ()" qui se comporte de la même manière, ce qui atténue le problème.

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