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

Linq Discussion :

[C#] from A in As from B in Bs from C in Cs en dynamic


Sujet :

Linq

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 69
    Points : 82
    Points
    82
    Par défaut [C#] from A in As from B in Bs from C in Cs en dynamic
    Bonjour,
    j’aimerai pouvoir optimiser mes jointure faite dynamiquement,
    en effet le code qui suit est quelque peu lent, ce qui nuit a l'utilisation du soft.
    J'ai vu sur des forums qu'il était possible de faire de multiple inner join sur une même table de la façon suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    from A in As 
    from B in Bs
    from C in Cs
    where A.ID == B.ID || A.ID == C.ID select A
    J'aimerrai pouvoir faire de même mais de façon dynamique via une methode, laquelle je ne trouve pas.


    Voici mon code de base que j'aimerrai optimiser :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
                IQueryable<Souscription> baseReq = req;
                req = null;
                foreach (var item in ModeSouscriptions)
                {
                    if (item is ModeSouscriptionAgence)
                    {
                        IQueryable<Souscription> souReq = from souscription in baseReq
                                                          join mode in Context.ModeSouscription.OfType<ModeSouscriptionAgence>()
                                                           on souscription.ModeSouscription_ModeSouscriptionID equals mode.ModeSouscriptionID
                                                          select souscription;
                        if (req == null)
                            req = souReq;
                        else
                            req = req.Union(souReq);
                    }
                    else if (item is ModeSouscriptionCourrier)
                    {
                        IQueryable<Souscription> souReq = from souscription in baseReq
                                                          join mode in Context.ModeSouscription.OfType<ModeSouscriptionCourrier>()
                                                           on souscription.ModeSouscription_ModeSouscriptionID equals mode.ModeSouscriptionID
                                                          select souscription;
                        if (req == null)
                            req = souReq;
                        else
                            req = req.Union(souReq);
                    }
    }
    Merci, a bientôt

  2. #2
    Membre expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Points : 3 173
    Points
    3 173
    Par défaut
    Peut'on voir la structure de vos tables?
    Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
    MCTS Database Development
    MCTS Database Administration

  3. #3
    Membre expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Points : 3 173
    Points
    3 173
    Par défaut
    en effet le code qui suit est quelque peu lent, ce qui nuit a l'utilisation du soft.
    Evidemment vous faites des requêtes dans une boucle!
    Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
    MCTS Database Development
    MCTS Database Administration

  4. #4
    Membre éprouvé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2007
    Messages
    693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 693
    Points : 1 187
    Points
    1 187
    Par défaut
    Bonjour,

    Euh...

    Quelle est l'utilité d'exécuter toujours la même requête (donc toujours le même résultat à chaque tour de boucle ?

    Dans le code donné qu'est-ce qui change à chaque tour ?
    • Item : qui n'est utilisé que pour son type
    • req qui est alimenté par le union via les soureq


    Essaye de retirer la boucle !

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 69
    Points : 82
    Points
    82
    Par défaut
    Merci de ces réponses,
    je vais essayer de supprimer la boucle, mais étant donné que c'est de l'linq to entities, normalement la requette est exécuter uniquement quand j'utilise le IQueryable (donc la boucle ne pause pas de problème), le Union est une source d’exécution SQL croyez-vous ?
    En générale je fais un ToList() après la construction de mon IQueryable pour exécuter ma requette en SQL.


    Pour la structure de la table, j'utilise l'abstraction fourni par EF pour tester le type d'une classe abstraite (je trouve cela pas mal).

    Je propose de filtrer selon les types dérivé de la classe de base qui elle est stocké dans une table comme un simple champ.
    Donc pour filtrer je fait des jointures internes avec les tables des classe dérivés.
    La liste de filtre est aléatoire , c'est pour cela que j'utilise une boucle.
    Le problème de la jointure interne est que je suis obligé de faire un union pour joindre ma requette sur plusieurs table d'un même champ.


    Voici une autre version, mais qui m'oblige a faire un Distinct en fin de requette ce qui réduit également les performances. Quand même moins que la version précèdent, mais c'est toujours pas ça.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     bool isModeSouscriptionAgence = false;
                bool isModeSouscriptionCourrier = false;
                bool isModeSouscriptionMail = false;
     
                foreach (var item in ModeSouscriptions)
                {
                    if (item is ModeSouscriptionAgence)
                        isModeSouscriptionAgence = true;
                    else if (item is ModeSouscriptionCourrier)
                        isModeSouscriptionCourrier = true;
                    else if (item is ModeSouscriptionMail)
                        isModeSouscriptionMail = true;
                }
     IQueryable<Souscription> req = from souscription in souscriptionSituations
                                               from modeSouscriptionAgence in Context.ModeSouscription.OfType<ModeSouscriptionAgence>()
                                               from modeSouscriptionCourrier in Context.ModeSouscription.OfType<ModeSouscriptionCourrier>()
                                               from modeSouscriptionMail in Context.ModeSouscription.OfType<ModeSouscriptionMail>()
                                               where (souscription.ModeSouscription_ModeSouscriptionID == modeSouscriptionAgence.ModeSouscriptionID && isModeSouscriptionAgence == true)
                                               || (souscription.ModeSouscription_ModeSouscriptionID == modeSouscriptionCourrier.ModeSouscriptionID && isModeSouscriptionCourrier == true)
                                               || (souscription.ModeSouscription_ModeSouscriptionID == modeSouscriptionMail.ModeSouscriptionID && isModeSouscriptionMail == true)
                                               select souscription;
    req.Distinct().ToList();

    Quand je fait un test de performance 30% de l’exécution ce fait dans req.Distinct().ToList();
    Merci.

  6. #6
    Membre expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Points : 3 173
    Points
    3 173
    Par défaut
    Peut'on voir la structure de vos tables?
    Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
    MCTS Database Development
    MCTS Database Administration

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 69
    Points : 82
    Points
    82
    Par défaut
    Voici la structure de mes tables


  8. #8
    Membre éprouvé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2007
    Messages
    693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 693
    Points : 1 187
    Points
    1 187
    Par défaut
    Citation Envoyé par neoncyber Voir le message
    je vais essayer de supprimer la boucle, mais étant donné que c'est de l'linq to entities, normalement la requette est exécuter uniquement quand j'utilise le IQueryable (donc la boucle ne pause pas de problème),
    Les choses inutiles font perdre du temps en général après je ne connais pas le détail de la mécanique interne du linq to sql mais moi moins j'en fais moins ça me prend de temps !

    Pour ça, je dirais que ça ne sert à rien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
       foreach (var item in ModeSouscriptions)
                {
                    if (item is ModeSouscriptionAgence)
                        isModeSouscriptionAgence = true;
                    else if (item is ModeSouscriptionCourrier)
                        isModeSouscriptionCourrier = true;
                    else if (item is ModeSouscriptionMail)
                        isModeSouscriptionMail = true;
                }
    Et pour la requête simplement ça, ça ne fonctionne pas ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    IQueryable<Souscription> req = from souscription in souscriptionSituations
                                               from modeSouscription in Context.ModeSouscription
                                               where (souscription.ModeSouscription_ModeSouscriptionID == modeSouscription.ModeSouscriptionID
                                     select souscription;

  9. #9
    Membre expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Points : 3 173
    Points
    3 173
    Par défaut
    Confirmez moi ce que vous voulez faire:
    Vous avez trois tables (qui se retrouve être de l'heritage une fois dans ENTITIES) et en fonction de 3 booleans (j'image....) vous voulez retourner l'union des tables ?
    Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
    MCTS Database Development
    MCTS Database Administration

  10. #10
    Membre expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Points : 3 173
    Points
    3 173
    Par défaut
    Voici la structure de mes tables
    Ce n'est pas une structure de table çà mais votre "modèle" LINQ TO ENTITIES
    Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
    MCTS Database Development
    MCTS Database Administration

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 69
    Points : 82
    Points
    82
    Par défaut


    En français ce que je veux faire ce dirai,

    Je veux toutes les souscriptions qui sont :
    Faite par mail.
    Faite par mail ou par agence.
    Faite par mail ou par agence ou par courrier.
    etc ...
    Exactement comme un filtre excel (d'ailleur l'IHM ressemble a excel).

    Pour ne pas utiliser d'enum qui me semble pas très correct en ORM, j'utilise
    une classe de base ModeSouscription, cette classe de base est utilisé dans UN seul champ de la classe qui l'utilise (souscriptions) et cette classe de base peut avoir plusieur dérivation (agence, courrier etc)

    C'est comme si souscription avait un champ enum qui peut contenir O,1,2

    Sauf que la ce champ contient 0,1,2 qui sont les ID des classe dérivés de mode souscriptions, comme ca pas besoin de savoir ce que c'est 0,1,2, car il suffit de tester le type de la classe a qui appartient cette ID.
    Pour tester le type en Linq au moment de la requette il faut faire un OfType.

    C'est un peu compliqué a expliquer...


    Je veux retourner l'union de trois resultat. Chaque resultat correspond a une liste de souscription de type derivé de modeSouscription.

    Ok il faut que je retourne sur terre au lieu de parler de class etc, je vais faire un screen de mes tables SQL !

  12. #12
    Membre expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Points : 3 173
    Points
    3 173
    Par défaut
    Pour ne pas utiliser d'enum qui me semble pas très correct en ORM, j'utilise
    Donc vos trois tables ModeSouscription_ ne contiennent que ModeSouscriptionId???

    Ces 3 tables n'ont pour moi pas vraiment lieu d'être et auraient pu être remplacés par des vues SQL.

    Etant spécialisé base de données cela me fait bondir naturellement mais qu'en pensent les pro du pattern .NET?
    Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
    MCTS Database Development
    MCTS Database Administration

  13. #13
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 080
    Points
    8 080
    Par défaut
    A moins que le modèle soit plus complet après en rajoutant des champs différents dans chaque table ModeSouscription, une enum aurait été largement adaptée!

    L'héritage n'est pas trop concu pour ce cas, c'est plutot "j'ai une entité Employee, Doctor et Nurse en héritent" et ca se modéliserait avec trois tables et un champ discriminant dans Employee. Et d'ailleurs, je suis pas sur qu'il soit possible d'obtenir une requete de l'union des Doctors et des Nurses dans le cas la...

  14. #14
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 69
    Points : 82
    Points
    82
    Par défaut
    Merci de vos réponse,
    Finalement je me suis un peu pris la tête est fait un builder de requette en eSQL
    qui permet de requetter une table selon les types dérivé d'un de ces champs.
    Je ne connai pas les vus SQL c'est grave... (ca doit pas être très ORM j'espere)
    Non mais vraiment a chaque foi que je vois un enum dans une base de donné sa me donne des boutons (peut être est-ce a cause de EF qui ne les gère pas encore correctement)
    Par ailleur CodeFirst permet un meilleur requettage SQL sur les heritages, vue que tous est dans la même table pas besoin de faire de distinct (j'ai oublié pourquoi).

    En gros mon eSQL fait des left join sur la classe ModeSouscription des different type, et fait un where pour selectionner uniquement ceux demandé...
    (en code first ce serrai different)

    Par ailleur un enum ne permet pas de faire des enum en arbre (comme de l'heritage).

    Dans un project cela ma permis de rajouter un comportement a une valeur d'un enum en le dérivant encore. Ce qui evite de rajouter cette nouvelle valeur d'enum dans toute les close if etc...

    Donc mon eSQL gère également l'expect pour des class sous dérivés,
    par exemple (totalement bidon) on demande modesouscriptioncourriermaison mais pas modesouscriptioncourrier tous cours.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
     
        public class FilterEntityType
        {
     
     
            public string getEntites( 
                List<Type> SelectFilterType,
                List<Type> ExpectFilterType, 
                string targetEntityCollection, 
                string baseFilterEntity,
                string targetEntityProprtyJoinID,
                string baseFilterEntityPropertyID,
                string namespaceBaseFilterEntity)
            {
                string joinQuerys = "";
     
                foreach (Type item in SelectFilterType)
                {
                    joinQuerys += string.Format(
                        "LEFT OUTER JOIN OFTYPE({0}, {1}.{2}) AS {2}Selector ON target.{3} == {2}Selector.{4} ",
                        baseFilterEntity,
                        namespaceBaseFilterEntity,
                        item.Name,
                        targetEntityProprtyJoinID,
                        baseFilterEntityPropertyID);
                }
     
                string whereIns = whereIn(SelectFilterType, baseFilterEntityPropertyID);
     
     
                string notIn = "";
     
                foreach (Type item in ExpectFilterType)
                {
                    notIn += string.Format("&& {0}Selector.{1} IS NULL ", item.Name, baseFilterEntityPropertyID);
                }
     
                string query = string.Format(
                    "SELECT VALUE target FROM {0} AS target {1} WHERE target.{2} IN {{{3}}} {4}",
                    targetEntityCollection,
                    joinQuerys,
                    targetEntityProprtyJoinID,
                    whereIns,
                    notIn
                    );
                return query;
            }
            private string whereIn(List<Type> FilterType, string baseFilterEntityPropertyID)
            {
                string whereInQuerys = "";
     
                foreach (Type item in FilterType)
                {
                    whereInQuerys += string.Format(
                        "{0}Selector.{1},",
                        item.Name,
                        baseFilterEntityPropertyID);
                }
                whereInQuerys = whereInQuerys.Remove(whereInQuerys.LastIndexOf(','));
     
                return whereInQuerys;
            } 
     
        }
    Un exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
           SELECT VALUE souscription FROM Souscriptions AS souscription 
                    LEFT OUTER JOIN OFTYPE(ModeSouscription,ConsoleApplication1.ModeSouscriptionCourrier) AS courrier ON souscription.ModeSouscription == courrier.Id 
                    LEFT OUTER JOIN OFTYPE(ModeSouscription,ConsoleApplication1.ModeSouscriptionAgence) AS agence ON souscription.ModeSouscription == agence.Id 
                    WHERE souscription.ModeSouscription_Id IN {agence.Id, courrier.Id}
    A bientôt !

  15. #15
    Membre expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Points : 3 173
    Points
    3 173
    Par défaut
    (ca doit pas être très ORM j'espere)
    Je rêve...
    Ce n'est pas une question d'être ORM ou pas (ce qui ne veut rien dire dailleurs...) c'est une question de faire les choses bien en se basant sur un langage (SQL) extrêmement normalisé...
    Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
    MCTS Database Development
    MCTS Database Administration

  16. #16
    Membre expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Points : 3 173
    Points
    3 173
    Par défaut
    Donc mon eSQL gère également l'expect pour des class sous dérivés,
    par exemple (totalement bidon) on demande modesouscriptioncourriermaison mais pas modesouscriptioncourrier tous cours.
    En bref une nouvelle usine à gaz pour rien du tout encore liée à une mauvaise modélisation...
    Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
    MCTS Database Development
    MCTS Database Administration

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

Discussions similaires

  1. [COUNT] select ... from ... where count !
    Par tmcgrady dans le forum Langage SQL
    Réponses: 5
    Dernier message: 30/11/2007, 17h29
  2. DELETE FROM t where t.id IN (SELECT id FROM t....)
    Par davcha dans le forum Langage SQL
    Réponses: 4
    Dernier message: 05/01/2006, 15h19
  3. SYBASE SELECT imbriqué clause FROM
    Par Nicolas Martel dans le forum Sybase
    Réponses: 2
    Dernier message: 19/11/2003, 15h28
  4. Automatiser la mise à jour de la bD SQL SERVER from Access
    Par Nadaa dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 11/11/2003, 15h23
  5. equivalent de select nextval from dual en SQL-Server ?
    Par toze dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 15/10/2003, 09h17

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