Partage
  • Partager sur Facebook
  • Partager sur Twitter

Linq Entities, problème quand valeur dans le where est null

Sujet résolu
    2 mai 2011 à 22:55:45

    Bonjour à tous,
    J'utilise actuellement Linq To Entities, hors je rencontre un problème avec une relation 0..1
    Si il y a une valeur (donc 1), tout fonctionne, par contre dans le cas où j'ai null en bdd, alors ça plante à cause de l'objet qui n'existe pas dans le where.

    Tout d'abord, voici ma solution
    Image utilisateur


    Ma récupération Linq To Entities:
    public class RequeteManager : Manager
        {
            public List<RequeteEntity> GetAll()
            {
                return Context.requete
                    .Include("provenance")
                    .ToList()
                    .Select(a=>new RequeteEntity()
                                   {
                                       Id = a.id_requete,
                                       Demande = a.demande,
                                       Provenance = Context.provenance
                                                        .Where(pr => pr.id_provenance == a.provenance.id_provenance)
                                                        .Select(pr => new ProvenanceEntity()
                                                                          {
                                                                              Id = pr.id_provenance,
                                                                              Nom = pr.nom
                                                                          })
                                                        .FirstOrDefault(),
     
                                        Priorite = Context.priorite
                                                        .Where(prio => prio.id_priorite == a.priorite.id_priorite)
                                                        .Select(prio => new PrioriteEntity(){
                                                                Id = prio.id_priorite,
                                                                Nom = prio.nom
                                                            })
                                                        .FirstOrDefault()
                                   })
                    .ToList();
            }
        }
    


    Ce qui coince c'est cette partie:
    .Where(prio => prio.id_priorite == a.priorite.id_priorite)
    Si il n'y a pas de priorité associée à une requête, la valeur du champs est "null" et j'ai donc le message suivant :
    Exception:Caught: Object reference not set to an instance of an object. (System.NullReferenceException)

    (C'est normal).

    Je me suis donc dit, je vais testé si la valeur est null:
    Priorite = Context.priorite
                                                        .Where(prio => a.priorite!=null)
                                                        .Where(prio => prio.id_priorite == a.priorite.id_priorite)
                                                        .Select(prio => new PrioriteEntity(){
                                                                Id = prio.id_priorite,
                                                                Nom = prio.nom
                                                            })
                                                        .FirstOrDefault()
    


    Et là:
    Exception:Thrown: Unable to create a constant value of type 'Closure type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context. (System.NotSupportedException)

    J'ai essayé : .Where(prio => prio.id_priorite == ((a.priorite==null)?2:a.priorite.id_priorite))

    Bref, je n'ai rien trouvé de concluant sur Google et je ne m'en sort pas.
    Comment puis je faire sans avoir à récupérer toutes mes demandes, puis faire un foreach derrière. J'aimerai tout faire dans la même requête.

    Comment puis je faire svp? des pistes?
    • Partager sur Facebook
    • Partager sur Twitter
      2 mai 2011 à 23:25:08

      Ca serait plutot quelque chose comme ça:

      return Context.requete
          .Include("provenance").Include("priorite")
          .ToList()
          .Select(a => new RequeteEntity()
          {
              Id = a.id_requete,
              Demande = a.demande,
              Provenance = new ProvenanceEntity()
              {
                  Id = a.provenance.id_provenance,
                  Nom = a.provenance.nom
              },
              Priorite = (a.priorite == null ? null : new PrioriteEntity()
              {
                  Id = a.priorite.id_priorite,
                  Nom = a.priorite.nom
              })
          })
          .ToList();
      

      Note que je ne comprends pas trop pourquoi tu as une classe Priorite (mappés à ta table Priorite) avec des propriétés id_priorite et nom, et une classe PrioriteEntity() avec des propriétés Id et Nom que tu dois mapper manuellement (et idem pour les autres tables). Tu te compliques méchamment la vie ! o_O

      Tu peux très bien demander à Entity Framework de mapper tes tables sur des classes dont le nom ainsi que le nom des propriétés sont différents des noms utilisés dans la base. Du coup, plus besoin de définir des entités et de faire le mapping manuellement pour avoir un modèle objet bien propre, EF fait tout ça pour toi ! :)
      • Partager sur Facebook
      • Partager sur Twitter
        3 mai 2011 à 8:48:40

        La lazy loading c'est le mal...
        • Partager sur Facebook
        • Partager sur Twitter
          3 mai 2011 à 9:30:04

          @ Orwell
          Un grand merci, il ne faut pas tester l'existance dans le where mais bel et bien comme tu l'as indiqué.
          J'y est passé un sacré moment sur ce point.

          Je vais essayer de t'éclaircir sur le fait que j'ai des classes mappées sur celle de l'EDMX.
          Je débute, donc ma méthode n'est peu être pas bonne.

          J'ai 5 projets dans ma solution - DAL : Accés au données, EDMX + mes managers, par exemple UserManager avec Add, Delete, ...
          - BLL : Métier
          - GUI : Interface Graphique
          - ET : Entités, les classes en questions.
          - TOOLS : Outils

          GUI référence BLL
          BLL référence DAL
          Et j'ai ET et TOOLS qui sont référencés dans toutes mes couches.
          Le but est d'avoir des entités qui sont indépendantes de la technologie. Si demain je n'utilise plus d'EDMX c'est possible.
          Si je veux utiliser une autre techno niveau IHM, c'est possible aussi.

          Je crois qu'en fait c'est un peu l'équivalent des POCO mais je en suis pas sûr.

          Sinon voilà mon code:
          return Context.requete
                          .Include("provenance")
                          .Include("priorite")
                          .ToList()
                          .Select(a=>new RequeteEntity()
                                         {
                                             Id = a.id_requete,
                                             Demande = a.demande,
                                             Provenance = Context.provenance
                                                              .Where(pr => pr.id_provenance == a.provenance.id_provenance)
                                                              .Select(pr => new ProvenanceEntity(){
                                                                                    Id = pr.id_provenance,
                                                                                    Nom = pr.nom
                                                                                })
                                                              .FirstOrDefault(),
          
                                             Priorite = (a.priorite!=null)?Context.priorite
                                                              .Where(prio => prio.id_priorite == a.priorite.id_priorite)
                                                              .Select(prio => new PrioriteEntity(){
                                                                                  Id = prio.id_priorite,
                                                                                  Nom = prio.nom
                                                                              })
                                                              .FirstOrDefault():null
                                         })
                          .ToList();
          

          • Partager sur Facebook
          • Partager sur Twitter
            3 mai 2011 à 11:22:54

            Citation : Takinelinfo

            Le but est d'avoir des entités qui sont indépendantes de la technologie. Si demain je n'utilise plus d'EDMX c'est possible.
            ...
            Je crois qu'en fait c'est un peu l'équivalent des POCO mais je en suis pas sûr.


            Tu peux aussi demander à EntityFramework de te générer des POCO :) Il y a un type de projet spécialement prévu pour ça.

            Citation : Takinelinfo

            Sinon voilà mon code:


            Tu aurais pu utiliser mon code directement, là tu te compliques encore la vie :)
            Par exemple quand tu fais ceci:

            Provenance = Context.provenance
                .Where(pr => pr.id_provenance == a.provenance.id_provenance)
                .Select(pr => new ProvenanceEntity(){
                    Id = pr.id_provenance,
                    Nom = pr.nom
                })
                .FirstOrDefault()
            


            Tu vas chercher dans ta base l'entité "provenance" qui possède le même id que l'entité a.provenance. Ben tu sais quoi ? C'est a.provenance ! :D Tu l'as déjà sous la main, pas besoin de le recharger :) Sans parler du fait que ton code génère un paquet de requêtes SQL pour aller chercher toutes les provenances une par une...

            • Partager sur Facebook
            • Partager sur Twitter

            Linq Entities, problème quand valeur dans le where est null

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
            • Editeur
            • Markdown