Partage
  • Partager sur Facebook
  • Partager sur Twitter

Quelqu'un a t'il déjà réalisée un projet en C#

Avec l'utilisation de LinqToEntities (EDMX)

    26 juillet 2011 à 15:18:49

    Bonjour à tous,

    Je développe mon premier projet en C# et je rencontre pas mal de difficultés quand aux stratégies pour récupérer mes données. J'ai à peut prêt une 30 de tables et des problèmes lorsque je cumule les .Include(). Si quelqu'un avait un peu de temps à m'accorder je lui en serait reconnaissant.
    Si des personnes sont ok pour me donner deux ou trois conseils, je posterais une image de mon EDMX, voir ma solution.

    Par avance merci à vous.
    • Partager sur Facebook
    • Partager sur Twitter
      26 juillet 2011 à 15:54:52

      Quels problèmes exactement?
      • Partager sur Facebook
      • Partager sur Twitter
        26 juillet 2011 à 15:58:26

        En fait j'ai besoin de récupérer plusieurs informations dans différente tables.
        Hors au bout d'un moment, il y a trop de .Include() et mon provider n'est plus content.
        Du coup je n’e sais pas comment faire
        • Partager sur Facebook
        • Partager sur Twitter
          26 juillet 2011 à 16:27:37

          Je pense que le mieux serait que tu nous montres ton modèle de données: un screenshot de ton modèle edmx fera l'affaire. Ensuite donne nous les requêtes qui ne passent pas, et on t'aidera à les réécrire autrement :)
          • Partager sur Facebook
          • Partager sur Twitter
            26 juillet 2011 à 16:28:03

            Commence par soigner ton orthographe... même a moi ça pique les yeux (c'est dire...)

            Ensuite, si j'ai bien compris, ton problème viens de la grande quantité d'info a récupérer? Pourquoi ne pas faire par petit bout?
            • Partager sur Facebook
            • Partager sur Twitter
              26 juillet 2011 à 17:07:19

              Voici mon EDMX.
              Image utilisateur

              C'est une application en WPF. Le principe est le suivant.
              J'ai un écran avec une vue maitre/détail.

              Vue maitre:
              Elle est composée de 5 onglets. Dans Chaque onglets j'ai une ListView avec un ensemble de compétitions.
              Exemple de colonne
              - Titre compétition
              - Région
              - Ville
              - L'avancement de la dernière épreuve
              - La difficulté

              Exemple: Onglet "en cours" > Ensemble des compétitions dont au moins une des épreuves à un avancement "non fini" et dont je fais parti des participants.

              Vue détail
              Lorsque je clique sur une compétition de la view maitre j'ai l'ensemble des détails qui doit apparaitre, c'est à dire:
              - La compétition
              - La région
              - La ville
              - La difficulté
              - Les sponsors
              - Les clubs
              - L’ensemble des épreuves
              - Les départements qui participent
              - Les utilisateurs qui participent
              - Le détail de chaque épreuve
              - ....

              Voici un exemple de ce que j'ai fait:
              var Db = new PostgresqlsportContext();
              Db.Connection.Open();
               
              var query = Db.competition
              	.Include("sponsor")
              	.Include("club")
              	.Include("region")
              	.Include("ville")
              	.Include("epreuve")
              	.Include("difficulte")
              	.Include("epreuve")
               
              	.Include("epreuve.directeur")
              	.Include("epreuve.superviseur")
              	.Include("epreuve.avancement")
              	.Include("epreuve.epreuve_detail")
              	.Include("epreuve.epreuve_detail.complexite_duree")
              	.Include("epreuve.epreuve_detail.complexite_distance")
              	.Include("epreuve.epreuve_detail.total_unite_duree")
              	.Include("epreuve.epreuve_detail.total_unite_distance")
              	.Include("epreuve.epreuve_detail.detail_duree")
              	.Include("epreuve.epreuve_detail.detail_distance")
              	.Include("epreuve.epreuve_detail.detail_distance.etape")
              	.Include("epreuve.epreuve_detail.detail_distance.etape_statut")
              	
              	//L'ensemble des conditions
              	.Where(...........);
               
              var nbResultQuery = query.Count();
              var e = query.ToList();
              


              Jusque là ça fonctionne, mais je n'ai pas tout les .Include() et quand j'en rajoute (par exemple) :

              Citation

              .Include("epreuve.epreuve_utilisateur_participant") .Include("epreuve.epreuve_utilisateur_participant.utilisateur");


              mon application n'est plus contente.

              Et là je ne sais pas comment faire pour avoir le même résultat sans multiplier par 100 le nombre de requêtes.
              • Partager sur Facebook
              • Partager sur Twitter
                26 juillet 2011 à 17:48:54

                Ah oui en effet, ça c'est de la requête sympa :D

                Note au passage: tu aurais du donner à tes collections un nom au pluriel (par exemple "epreuves" au lieu de "epreuve" dans l'entité "compétition", parce que là c'est assez peu lisible :-° ). Idem pour le nom des tables.
                Note 2: Pense à faire ton Count() sur le résultat de la requête, parce que là tu lances la requête 2 fois (une première fois avec un SELECT COUNT(*), et la seconde avec un SELECT).
                Note 3 : tu as inclus epreuve 2 fois.

                Je pense que tu as intérêt à décomposer ta requête en plusieurs parties... A mon avis PostgreSQL t'envoie balader parce que ta requête est trop longue :-°

                Essaie comme ceci par exemple:
                EDIT: Bon je me suis fourvoyé, on ne peut pas combiner Include() et Load(). :(

                Malheureusement la seule solution que je vois serait de charger séparément la liste des épreuves; tu ne pourrais donc pas profiter de la collection competition.epreuve :(

                var competitions = Db.competition
                    .Include("sponsor")
                    .Include("club")
                    .Include("region")
                    .Include("ville")
                    .Include("difficulte")
                    .Where(....)
                    .ToList(); // on charge dejà les compétitions sans les épreuves
                    
                foreach(competition comp in competitions)
                {
                    var epreuves = Db.epreuve
                        .Include("directeur")
                        .Include("superviseur")
                        .Include("avancement")
                        .Include("epreuve_detail")
                        .Include("epreuve_detail.complexite_duree")
                        .Include("epreuve_detail.complexite_distance")
                        .Include("epreuve_detail.total_unite_duree")
                        .Include("epreuve_detail.total_unite_distance")
                        .Include("epreuve_detail.detail_duree")
                        .Include("epreuve_detail.detail_distance")
                        .Include("epreuve_detail.detail_distance.etape")
                        .Include("epreuve_detail.detail_distance.etape_statut")
                        .Include(".......")
                        .Where(e => e.id_competition = comp.id_competition)
                        .ToList(); // on charge séparémentles épreuves de cette compétition
                        
                    // faire quelque chose avec cette liste d'épreuves (qui n'est malheureusement pas attachée à l'entité compétition)
                }
                


                Bien sûr ce n'est pas idéal de multiplier le nombre de requêtes, mais tu n'as sans doute pas des centaines de compétitions à afficher donc ça devrait aller.

                Une meilleure solution serait sans doute de ne charger la liste des épreuves qu'au moment où l'utilisateur choisit une compétition particulière dont il veut voir le détail :)
                • Partager sur Facebook
                • Partager sur Twitter
                  27 juillet 2011 à 9:19:24

                  Note 1 : Hihi, c'est pas faux. En fait je mets mes tables (BDD) au singulier et sous PHP j'ai l'habitude d'utiliser le singulier.
                  Il faudrait en effet que j'utilise le pluriel, ça parlerait un peu plus.

                  Note 2 : En fait je fesais query.Count(); et non query.ToList().Count() parce qu'avec MySQL Connector 6.3.4 j'avais une différence entre les deux (c'est d'ailleur pour ça que je suis sur PostgreSQL maintenant).
                  Mais tu as raison de le préciser.

                  Note 3 : Yes, j'ai oublié de le retirer. A la base c'était pour voir comment EF réagissait. Il n'a pas l'air dans tenir compte mais je le retire.

                  Citation

                  Je pense que tu as intérêt à décomposer ta requête en plusieurs parties... A mon avis PostgreSQL t'envoie balader parce que ta requête est trop longue


                  Je crois que quelque soit le SGBD, il m'envoit balader. Avec MySQL Connector j'avais un message du style "Impossible de faire une jointure sur plus de 61 tables).

                  Citation

                  Malheureusement la seule solution que je vois serait de charger séparément la liste des épreuves; tu ne pourrais donc pas profiter de la collection competition.epreuve


                  Merci pour cette idée.
                  En fait l'EDMX fournit est une copie de ma vrai application (j'ai remplacé les noms). Il s'avère que dans certain onglets je peux avoir jusqu'à 1000 compétitions.
                  - 1 requêtes pour récupérer les 1000 compétitions.
                  - 1000 requêtes pour récupérer la liste des epreuves. :(

                  Citation

                  Une meilleure solution serait sans doute de ne charger la liste des épreuves qu'au moment où l'utilisateur choisit une compétition particulière dont il veut voir le détail


                  En fait si je charge tout c'est parce que dans ma vue maitre, dans ma listview, j'ai quelques détails sur la compétition MAIS AUSSI sur la dernière étape.
                  ça permet notamment de pouvoir faire des tries.

                  Par contre sur ton principe, je pourrais peut être faire une requête avec seulement les infos qui doivent apparaitre dans la listview, et lorsque l'on clique dessus, je viens charger les détails.


                  N'y a t'il pas une méthode (je ne pense pas mais je demande) qui pourrait ressemebler à ceci:
                  var competitions = Db.competition
                      .Include("sponsor")
                      .Include("club")
                      .Include("region")
                      .Include("ville")
                      .Include("difficulte")
                      .Where(....)
                      .AsEnurable();
                  	
                  competitions
                  	.Include("epreuve")
                  	.Include("directeur")
                  	.Include("superviseur")
                  	.Include("avancement")
                  	.Include("epreuve_detail")
                  	.Include("epreuve_detail.complexite_duree")
                  	.Include("epreuve_detail.complexite_distance")
                  	.Include("epreuve_detail.total_unite_duree")
                  	.Include("epreuve_detail.total_unite_distance")
                  	.Include("epreuve_detail.detail_duree")
                  	.Include("epreuve_detail.detail_distance")
                  	.Include("epreuve_detail.detail_distance.etape")
                  	.Include("epreuve_detail.detail_distance.etape_statut")
                  	.Include(".......");
                  	
                  //En fait n'avoir que deux requêtes 
                  



                  Sur un autre forum on m'a parlé de ça
                  "Tu as d'autres techniques avec Entities: charger chaque table distinctement avec le même datacontext: c'est ENTITIES qui se charge de refaire les relation en mémoire... "
                  On m'a également donné un lien intéréssant
                  Je vais donc y jeter un coup d'oeil, et vous dire ce que j'en pense.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    27 juillet 2011 à 12:42:48

                    Citation : Takinelinfo

                    Note 1 : Hihi, c'est pas faux. En fait je mets mes tables (BDD) au singulier et sous PHP j'ai l'habitude d'utiliser le singulier.
                    Il faudrait en effet que j'utilise le pluriel, ça parlerait un peu plus.


                    D'autant qu'EF t'a proposé de le faire tout seul au moment de générer ton edmx :p

                    Citation : Takinelinfo

                    En fait si je charge tout c'est parce que dans ma vue maitre, dans ma listview, j'ai quelques détails sur la compétition MAIS AUSSI sur la dernière étape.
                    ça permet notamment de pouvoir faire des tries.


                    Même dans ce cas, ce n'est vraiment pas raisonnable de charger autant de données pour alimenter tes listes ! :o Tu ne devrais charger que le strict nécessaire.

                    Par contre sur ton principe, je pourrais peut être faire une requête avec seulement les infos qui doivent apparaitre dans la listview, et lorsque l'on clique dessus, je viens charger les détails.

                    En fait dans ce cas je vois deux solutions à ton problème:

                    1) Faire une requête de type Join() qui charge les compétitions et leur dernière épreuve. Tu peux t'inspirer de l'exemple que j'ai donné pour Join() dans l'autre topic :)

                    2) définir une Vue dans ta base de données dont les colonnes sont les informations qui apparaissent dans tes listes (ou qui servent à filtrer). De cette manière toutes les jointures sont faites dans la définition de la vue et il suffit de la requêter simplement pour en tirer ce qui t'intéresse ;)
                    Entity Framework ne supporte hélas pas nativement ce genre de vues, mais cette extension fait parfaitement l'affaire ^^


                    Citation : Takinelinfo

                    Sur un autre forum on m'a parlé de ça
                    "Tu as d'autres techniques avec Entities: charger chaque table distinctement avec le même datacontext: c'est ENTITIES qui se charge de refaire les relation en mémoire... "
                    On m'a également donné un lien intéréssant
                    Je vais donc y jeter un coup d'oeil, et vous dire ce que j'en pense.



                    La video a au moins le mérite d'insister sur le fait que charger la quasi-totalité de ta base en une seule requête comme tu le fais, c'est une catastrophe :p
                    Cela dit la technique qui consiste à requêter chaque table séparément et à laisser EF rétablir les liens entre les entités est intéressante :)
                    • Partager sur Facebook
                    • Partager sur Twitter
                      27 juillet 2011 à 16:11:54

                      Citation

                      D'autant qu'EF t'a proposé de le faire tout seul au moment de générer ton edmx :p


                      FAUX => je suis PostgreSQL et j'utilise Npgsql :( Du coup je génère l'EDMX à la main (Edmgen.exe et Edmgen2.exe)

                      Les vues j'y avais pensé mais je ne pensais pas que EntityFramework pouvait les supporter.
                      Et si je rajoute à ça que j'utilise Npgsql, ce n'est pas gagné.

                      Je vais regarder la vidéo ce soir car je suis au taff et je n'ai pas de son sur mon PC :)
                      • Partager sur Facebook
                      • Partager sur Twitter
                        27 juillet 2011 à 16:41:19

                        Citation : Takinelinfo

                        Citation

                        D'autant qu'EF t'a proposé de le faire tout seul au moment de générer ton edmx :p


                        FAUX => je suis PostgreSQL et j'utilise Npgsql :( Du coup je génère l'EDMX à la main (Edmgen.exe et Edmgen2.exe)


                        Il doit bien y avoir un argument à fournir à edmgen non ? :-°
                        • Partager sur Facebook
                        • Partager sur Twitter
                          27 juillet 2011 à 16:58:53

                          Faut que je regarde.
                          Par contre quand on créé un EDMX via Visual Studio, on peux chosir d'importer des tables, des views et des procédures. Du coup à quoi sert l'extension?
                          • Partager sur Facebook
                          • Partager sur Twitter
                            27 juillet 2011 à 17:13:57

                            Le support natif des vues est assez limité et ne gère pas correctement les relations avec les autres tables. Cette extension permet de corriger ça :)
                            • Partager sur Facebook
                            • Partager sur Twitter
                              28 juillet 2011 à 11:17:41

                              Le webcast répond parfaitement à ma problématique.
                              La solution avancée me plait pas mal par contre impossible de la faire fonctionner.

                              var competitionList = database.competition.ToList();	// OK
                              IEnumerable<int> competitionIdList = competitionList.Select(c => c.id_competition);	//Ok
                              var epreuveList = database.epreuve.Where(o => competitionIdList.Contains(o.id_competition)).ToList();	//Erreur
                              


                              Citation

                              ### Exception
                              Message: LINQ to Entities does not recognize the method 'Boolean Contains[Int32](System.Collections.Generic.IEnumerable`1[System.Int32], Int32)' method, and this method cannot be translated into a store expression.
                              Type: System.NotSupportedException
                              Source: System.Data.Entity



                              Est ce que ça vient de mon provider où j'ai fait une erreur quelque part?


                              ######
                              Edit
                              ######
                              Après plusieurs test, je pense pouvoir affirmer que c'est un problème de version de Framwork.
                              Je viens de tester sur un projet avec le Framework 4 et je n'ai plus l'erreur.
                              C'est la mauvaise nouvelle de la journée.
                              • Partager sur Facebook
                              • Partager sur Twitter

                              Quelqu'un a t'il déjà réalisée un projet en C#

                              × 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