web-dev-qa-db-fra.com

Seuls les initialiseurs, membres d'entité et propriétés de navigation d'entité sont pris en charge

Je reçois cette exception:

Le type de membre spécifié 'Payé' n'est pas pris en charge dans LINQ to Entities . Seuls les initialiseurs, les membres d'entité et les propriétés de navigation d'entité sont pris en charge.

    public ActionResult Index()
    {
        var debts = storeDB.Orders
            .Where(o => o.Paid == false)
            .OrderByDescending(o => o.DateCreated);

        return View(debts);
    }

Ma classe de modèle

public partial class Order
{
    public bool Paid {
        get {
            return TotalPaid >= Total;
        }
    }

    public decimal TotalPaid {
        get {
            return Payments.Sum(p => p.Amount);
        }
    }

Paiements est une table liée contenant le montant du champ. La requête fonctionne si je supprime la clause Where indiquant des informations correctes sur les paiements, aucun indice sur le problème du code?

Résolu comme la réponse suggérée avec:

    public ActionResult Index()
    {
        var debts = storeDB.Orders
            .OrderByDescending(o => o.DateCreated)
            .ToList()
            .Where(o => o.Paid == false);

        return View(debts);
    }
94
Marc

Entity tente de convertir votre propriété Paid en SQL et ne le peut pas car elle ne fait pas partie du schéma de la table. 

Ce que vous pouvez faire est de laisser Entity interroger la table sans filtre de paiement, puis filtrer ceux qui ne le sont pas.

public ActionResult Index()
{
    var debts = storeDB.Orders
        //.Where(o => o.Paid == false)
        .OrderByDescending(o => o.DateCreated);

    debts = debts.Where(o => o.Paid == false);

    return View(debts);
}

Bien entendu, cela voudrait dire que vous apporteriez toutes les données au serveur Web et que vous les filtreriez. Si vous souhaitez filtrer sur le serveur de base de données, vous pouvez créer une colonne calculée sur la table ou utiliser une procédure stockée.

106
Eugene S.

Je viens juste de résoudre un problème similaire ... Les solutions ci-dessus nécessitent un traitement en mémoire, ce qui est une mauvaise pratique (chargement paresseux).

Ma solution consistait à écrire une aide qui renvoyait un prédicat:

public static class Extensions
{
    public static Expression<Func<Order, bool>> IsPaid()
    {
        return order => order.Payments.Sum(p => p.Amount) >= order.Total;
    }
}

Vous pouvez réécrire votre déclaration linq en tant que:

var debts = storeDB.Orders
                    .Where(Extensions.IsPaid())
                    .OrderByDescending(o => o.DateCreated);

C'est pratique lorsque vous souhaitez réutiliser la logique de calcul (DRY) . Le seul inconvénient est que la logique ne fait pas partie de votre modèle de domaine.

23
Koen Luyten

Linq convertit les instructions en instructions SQL et les exécute en base de données.

Maintenant, cette conversion ne se produit que pour les entités membres, les initialiseurs et les propriétés de navigation d'entité ..__ Donc, pour obtenir une fonction ou une comparaison de propriété, nous devons d'abord les convertir en une liste en mémoire, puis appliquer une fonction pour récupérer des données.

Donc en totalité, 

var debts = storeDB.Orders.toList()
        .Where(o => o.Paid == false)
        .OrderByDescending(o => o.DateCreated);
14
T Gupta

Ce problème peut également provenir d'une propriété [NotMapped] qui porte le même nom dans votre modèle de base de données et votre modèle de vue.

AutoMapper essaie de le sélectionner dans la base de données pendant une projection. et la propriété NotMapped n’existe évidemment pas dans la base de données.

La solution consiste à Ignore la propriété dans la configuration d'AutoMapper lors du mappage du modèle de base de données vers le modèle d'affichage.

  1. Recherchez une propriété [NotMapped] avec le nom Foo dans votre modèle de base de données.
  2. Recherchez une propriété portant le même nom, Foo, dans votre modèle de vue.
  3. Si tel est le cas, modifiez votre configuration AutoMapper. Ajouter .ForMember(a => a.Foo, b => b.Ignore()); 
13
Jess

L'autre raison probable est que vous utilisez IEnumerable pour votre propriété, au lieu de ICollection

Donc au lieu de:

public class This
{
    public long Id { get; set; }
    //...
    public virtual IEnumerable<That> Thats { get; set; }
}

Faire ceci:

public class This
{
    public long Id { get; set; }
    //...
    public virtual ICollection<That> Thats { get; set; }
}

Et tu es un dory ... une chose stupide de perdre 2 heures de plus.

11
Serj Sagan

Cette situation peut également se produire si vous utilisez non pris en charge par les types EntityFramework} _, tel que unsigned int.

_ {C'était mon cas d'une telle erreur.

Pour en savoir plus sur les types pris en charge: https://msdn.Microsoft.com/en-us/library/ee382832(v=vs.100).aspx

Il existe une solution de contournement pour de telles situations, expliquée par GFoley83: Comment utiliser des types unsigned int/long avec Entity Framework?

2
Ony

J'ai rencontré ce problème car j'avais une variable membre avec uniquement getwithout setproperty 

cela signifie que ses auto calculated et not stored sous forme de colonne dans the table 

donc son not exist dans le table schema 

so make sure que toute variable membre not auto calculated à have a une propriété getter et setter 

0
Basheer AL-MOMANI