2010-07-29 4 views
9

J'ai un modèle Entity Framework (v.1.0) que je suis en train de s'étend avec une propriété calculée.Entity Framework Calculée problème de la propriété

J'ai créé la classe partielle pour étendre l'objet entité « offre » de cette façon:

namespace MyModelNamespace 
{ 
    public partial class Offer 
    { 
     public bool MyProperty 
     { 
      get 
      { 
       // my stuffs the return true or false 
      } 
     } 
    } 
} 

Il compile sans problème dans mon assemblée, mais à l'exécution, quand je suis en train de faire quelque chose comme ceci:

_myEntities.OfferSet.FirstOrDefault(o=>o.MyProperty); 

je récupère cette erreur:

The number of members in the conceptual type 'MyModelNamespace.Offer' does not match with the number of members on the object side type 'MyModelNamespace.Offer'. Make sure the number of members are the same.

... des suggestions ???

Répondre

5

Oui, vous pouvez le faire. Utilisez le LINQ translations library.

+0

intéressant ... Je vais essayer dès que possible! – tanathos

+2

Je suis en train, mais je ne peux pas le faire travailler :(... J'ai inclus le dll, et il compile bien, mais à l'exécution je reçois quelque chose comme: « membre spécifié « MyProperty » non pris en charge par LINQ to Entities. ". J'ai exactement suivi les exemples dans le lien que vous avez publié. – tanathos

+0

@tanathos Votre problème a probablement à voir avec l'initialisation statique. Voir le commentaire de Matyas Boros d'Août 30e cet article.La solution de contournement proposée ici consiste à créer un constructeur statique (vide) sur la classe, puis à instancier une instance de l'objet avant qu'il ne soit interrogé. Ugly :( – AaronSieb

1

Vous ne pouvez pas pousser des propriétés personnalisées vers le bas à la base de données. Vous devriez avoir obtenu quelque chose comme

"The specified type member 'MyProperty' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."

La seule façon valable de faire ce que vous voulez est de l'avoir en mémoire. Et puis filtrez.

_myEntities.OfferSet.ToList().FirstOrDefault(o=>o.MyProperty); 

Je suppose qu'il y a probablement une meilleure façon d'accomplir tout ce que vous faites.

EDIT Je suis d'accord Craig il existe un autre moyen, en supposant que * il peut être traduit en une expression de magasin. Si vous mappez une propriété à un type de requête, vous pouvez rechercher/pousser le filtre.

+0

Pas le seul moyen; vois ma réponse. –

+0

Vous avez raison, je supposais qu'il essayait d'utiliser un certain type de propriété constante ou dérivée. – Nix

+0

'AsEnumerable()' est meilleur que 'ToList()' dans ce cas. –

0

Une façon vous pouvez essayer est d'utiliser l'espace de noms System.Linq.Expressions et la méthode d'extension AsExpandable disponible here.

Je pense que vous pourriez passer une expression à la méthode FirstOrDefault, et si vous voulez toujours utiliser MyProperty ailleurs, vous pouvez utiliser la même expression pour calculer sa valeur. Donc, vous auriez quelque chose comme:

public partial class Offer 
{ 
    public static Expression<Func<Offer, bool>> exp 
    { 
     get 
     { 
      return o => o.Property1 * o.Property2 == someValue; 
     } 
    } 

    public bool MyProperty 
    { 
     get 
     { 
      return exp.Compile()(this); 
     } 
    } 
} 

Puis, plus tard, vous le transmettre dans:

_myEntities.OfferSet.AsExpandable().FirstOrDefault(Offer.exp.Compile())); 

Si votre calcul peut être transformé en un arbre d'expression que SQL comprend, je pense que cela va fonctionner . Cela a fonctionné avec une classe de test non-Entité, mais l'utiliser avec LINQ to Entities est un animal différent.

Je ne l'ai pas utilisé AsExpandable beaucoup, donc ce code peut ne pas être bon. Je suis ouvert aux corrections.

+0

'MyFunc' devrait être un' Expression

+0

Bon point, ce qui signifie que le lambda doit être une expression à la place d'un bloc de déclaration, donc j'espère que le calcul peut être exprimé de cette façon. –

Questions connexes