IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Accès aux données Discussion :

[EF] Sous-requête Where, Many-to-Many


Sujet :

Accès aux données

  1. #1
    Membre Expert Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Par défaut [EF] Sous-requête Where, Many-to-Many
    Deux classes, Entry et Category, partagent une relation many-to-many.

    Je cherche à réaliser un moteur de recherche permettant, notamment, de rechercher toutes les Entry qui apparaissent dans une des catégories d'une liste de catégories.

    J'ai donc fait ceci :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    var result = ..... Toutes les Entries de ma base....;
    var categories = .... On récupère la liste des catégories...;
    if(categories.Count() > 0){
      results = from r in results
        where r.Categories.Any(c => categories.Contains(c))
        select r;
    }

    Et j'ai cette erreur :
    Citation Envoyé par l'erreur
    System.NotSupportedException was unhandled
    Message="The specified type member 'Categories' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."
    Source="System.Data.Entity"
    StackTrace:
    à System.Data.Objects.ELinq.ExpressionConverter.MemberAccessTranslator.TypedTranslate(ExpressionConverter parent, MemberExpression linq)
    à System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
    à System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
    .... blablabla....
    Des idées ?

  2. #2
    Membre Expert Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Par défaut
    J'ai trouvé, en fait, ça vient du fait que la propriété Categories n'est pas une propriété de navigation, mais une propriété ajoutée à la main.

    En effet, Entry dérive en Contact et Organisation. Et ce sont Contact et Organisation qui disposent de la propriété de navigation Categories....

    Par contre, c'est pas réglé pour autant, en se branchant sur Contact ou Organisation, j'obtiens une erreur au niveau de la méthode "Contains" que EF ne semble pas supporter.....

  3. #3
    Membre Expert Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Par défaut
    EF ne supporte pas les choses comme :

    var list = new int{1,2,3,4};
    var result = context.Entities.Where(e=>list.Contains(e));

  4. #4
    Membre éprouvé Avatar de anthyme
    Homme Profil pro
    Inscrit en
    Mars 2004
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 559
    Par défaut
    euhhh comment une entité pourrait être un int ?

  5. #5
    Membre Expert Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Par défaut
    Erreur d'inattention, désolé ^^
    Je voulais dire :

    var list = context.Entities.Where(e=>list.Contains(e.ID));

    Ceci dit, dans mon cas, il s'agit bien d'entitées :
    var categories = ... une sélection de catégories;
    var list = context.Entries.Where(e=>e.Categories.Any(c=>categories.Contains(c)));

    Mais ça ne change rien au problème : ce que ne gère pas EF, ce sont les listes d'objets externes au modèle. Que ces objets soient des types primitifs, des structs, des classes, ou des entités, ça n'a pas d'importance.

  6. #6
    Membre Expert Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Par défaut
    J'ai trouvé ceci pour transformer une expression Set.Contains en un équivalent utilisable par EF.

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    static Expression<Func<TElement, bool>> BuildContainsExpression<TElement, TValue>(
    	Expression<Func<TElement, TValue>> valueSelector,
    	IEnumerable<TValue> values)
    {
    	if ( null == valueSelector ) { throw new ArgumentNullException("valueSelector"); }
    	if ( null == values ) { throw new ArgumentNullException("values"); }
    	ParameterExpression p = valueSelector.Parameters.Single();
    	if ( !values.Any() ) {
    		return e => false;
    	}
    	var equals = values.Select(value => ( Expression )Expression.Equal(valueSelector.Body, Expression.Constant(value, typeof(TValue))));
    	var body = equals.Aggregate<Expression>((accumulate, equal) => Expression.Or(accumulate, equal));
    	return Expression.Lambda<Func<TElement, bool>>(body, p);
    }

    Petite particularité dans mon cas, néanmoins :

    Ceci ne marchera pas :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var filter = BuildContainsExpression<Category, Guid>(c=>c.ID, categories.Select(c=>c.ID));
    var results = context.Entities.Where(e=>e.Categories.Any(filter));

    Alors que ceci fonctionnera :

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var filter = BuildContainsExpression<Category, Guid>(c=>c.ID, categories.Select(c=>c.ID));
    var results = context.Entities.Where(e=>e.Categories.AsQueryable().Any(filter));

    Hé oui, sinon, on tape dans les méthodes d'extension de IEnumerable.

  7. #7
    Membre éprouvé Avatar de anthyme
    Homme Profil pro
    Inscrit en
    Mars 2004
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 559
    Par défaut
    merci de partager ton expérience

    (perso ça pourrais me servir un jour)

  8. #8
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 203
    Par défaut
    si tu veux faire un "WHERE IN" en EF regarde la class QueryableExtensions à la fin du thread suivant

    http://social.msdn.microsoft.com/for...-b7e4a1ab59f0/

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Appeler le champ d'une sous-requête where dans un select
    Par purplebamboo dans le forum PL/SQL
    Réponses: 2
    Dernier message: 24/06/2013, 15h07
  2. Sous-requête Where, ManyToMany
    Par Joffrey Kern dans le forum Entity Framework
    Réponses: 2
    Dernier message: 09/06/2011, 09h11
  3. Hibernate Update sous sélection sur Many-to-many
    Par chang_koukaii dans le forum Hibernate
    Réponses: 0
    Dernier message: 06/12/2007, 12h19
  4. Un peu de mal a comprendre le concepte "one-to-many" et "many-to-many"
    Par chriscoolletoubibe dans le forum Hibernate
    Réponses: 4
    Dernier message: 29/03/2007, 18h50
  5. Réponses: 3
    Dernier message: 08/08/2006, 15h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo