138 votes

LINQ to Entities ne reconnaît pas la méthode

J'obtiens l'erreur suivante lorsque j'essaie de faire une requête linq :

LINQ to Entities ne reconnaît pas la méthode ' IsCharityMatching(System.String, System.String)', et cette méthode ne peut pas être tracée. ne peut pas être traduite en une expression de magasin.

J'ai lu beaucoup de questions précédentes où les gens obtiennent la même erreur, et si je comprends bien, c'est parce que LINQ to Entities exige que toute l'expression de la requête linq soit traduite en une requête serveur, et donc on ne peut pas appeler une méthode extérieure dans cette expression. Je n'ai pas encore réussi à convertir mon scénario en quelque chose qui fonctionne, et mon cerveau commence à fondre, alors j'espérais que quelqu'un pourrait m'orienter dans la bonne direction. Nous utilisons Entity Framework et le modèle de spécification (et je suis nouveau dans les deux cas).

Voici le code qui utilise la spécification :

ISpecification<Charity> specification = new CharitySearchSpecification(charityTitle, charityReference);

charities = charitiesRepository.Find(specification).OrderBy(p => p.RegisteredName).ToList();

Voici l'expression linq :

public System.Linq.Expressions.Expression<Func<Charity, bool>> IsSatisfied()
{
    return p => p.IsCharityMatching(this.charityName, this.charityReference);
}

Voici la méthode IsCharityMatching :

public bool IsCharityMatching(string name, string referenceNumber)
{
    bool exists = true;

    if (!String.IsNullOrEmpty(name))
    {
        if (!this.registeredName.ToLower().Contains(name.ToLower()) &&
            !this.alias.ToLower().Contains(name.ToLower()) &&
           !this.charityId.ToLower().Contains(name.ToLower()))
        {
            exists = false;
        }
    }

    if (!String.IsNullOrEmpty(referenceNumber))
    {
        if (!this.charityReference.ToLower().Contains(referenceNumber.ToLower()))
        {
            exists = false;
        }
    }

    return exists;
}

N'hésitez pas à me contacter si vous avez besoin de plus d'informations.

Merci beaucoup,

Annelie

141voto

StriplingWarrior Points 56276

Comme vous l'avez compris, Entity Framework ne peut pas exécuter votre code C# dans le cadre de sa requête. Il doit être capable de convertir la requête en une véritable instruction SQL. Pour que cela fonctionne, vous devez restructurer votre expression de requête en une expression qu'Entity Framework peut traiter.

public System.Linq.Expressions.Expression<Func<Charity, bool>> IsSatisfied()
{
    string name = this.charityName;
    string referenceNumber = this.referenceNumber;
    return p => 
        (string.IsNullOrEmpty(name) || 
            p.registeredName.ToLower().Contains(name.ToLower()) ||
            p.alias.ToLower().Contains(name.ToLower()) ||
            p.charityId.ToLower().Contains(name.ToLower())) &&
        (string.IsNullOrEmpty(referenceNumber) ||
            p.charityReference.ToLower().Contains(referenceNumber.ToLower()));
}

1voto

Gerardo Sánchez Points 1297

J'ai obtenu la même erreur dans ce code :

 var articulos_en_almacen = xx.IV00102.Where(iv => alm_x_suc.Exists(axs => axs.almacen == iv.LOCNCODE.Trim())).Select(iv => iv.ITEMNMBR.Trim()).ToList();

c'est exactement l'erreur qui s'est produite :

System.NotSupportedException : 'LINQ to Entities ne reconnaît pas la méthode 'Boolean Exists(System.Predicate`1[conector_gp.Models.almacenes_por_sucursal])', et cette méthode ne peut pas être traduite en une expression de magasin.'

J'ai résolu le problème de cette manière :

var articulos_en_almacen = xx.IV00102.ToList().Where(iv => alm_x_suc.Exists(axs => axs.almacen == iv.LOCNCODE.Trim())).Select(iv => iv.ITEMNMBR.Trim()).ToList();

J'ai ajouté un .ToList() avant ma table, ce qui permet de découpler l'Entité et le code linq, et d'éviter que ma prochaine expression linq soit traduite

NOTE : cette solution n'est pas optimale, car elle évite le filtrage des entités et charge simplement toutes les tables en mémoire

1voto

JTIM Points 331

J'ai rencontré le même problème aujourd'hui, et c'est le premier lien que j'ai consulté. Cependant, je ne cherchais pas à vérifier ma requête. Donc si quelqu'un d'autre a le même problème et cherche cette solution, elle est ajoutée ici. Mon problème se situait dans un autre lien .

Il s'agit de l'exception la plus courante lorsque l'on travaille avec le cadre d'entités et que l'on convertit les données en résultats IQueryable pour le filtrage.

using (var context = new CustomerContext())
{
    var item = context.InvoiceItems
        .Where(i => i.Code == code.ToString())
        .FirstOrDefault();
}

Plusieurs solutions existent. Déplacer l'appel à ToString() sur une ligne séparée.

using (var context = new CustomerContext())
{
    string codeStr = code.ToString();
    var item = context.InvoiceItems
        .Where(i => i.Code == codeStr)
        .FirstOrDefault();
}

Utiliser la méthode d'extension EF,

using (var context = new CustomerContext())
{
    var item = context.InvoiceItems
        .Where(i => i.Code == SqlFunctions.StringConvert(code))
        .FirstOrDefault();
}

Convertir le résultat IQueryable en IEnumerable avant le filtrage

using (var context = new CustomerContext())
{
    var item = context.InvoiceItems.AsEnumerable()
        .Where(i => i.Code == code.ToString())
        .FirstOrDefault();
}

0voto

Mik Points 599

Si quelqu'un cherche une réponse en VB.Net (comme je l'ai fait au départ), la voici :

Public Function IsSatisfied() As Expression(Of Func(Of Charity, String, String, Boolean))

Return Function(charity, name, referenceNumber) (String.IsNullOrWhiteSpace(name) Or
                                                         charity.registeredName.ToLower().Contains(name.ToLower()) Or
                                                         charity.alias.ToLower().Contains(name.ToLower()) Or
                                                         charity.charityId.ToLower().Contains(name.ToLower())) And
                                                    (String.IsNullOrEmpty(referenceNumber) Or
                                                     charity.charityReference.ToLower().Contains(referenceNumber.ToLower()))
End Function

-3voto

Sameer Bahad Points 179

J'ai obtenu la même erreur dans ce code :

Solution

IQueryable a .toList() est la meilleure option

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