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

Entity Framework Discussion :

Rapidité avec ou sans EF


Sujet :

Entity Framework

  1. #1
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 122
    Points
    122
    Par défaut Rapidité avec ou sans EF
    Salut,

    J'étais habitué à tout monter "à la main" mais je me suis dit qu'EF pouvait faire une grosse partie du travail. alors j'ai tenté l'aventure EF.
    Je suis en Framework 4.8 et je suis en lié à PostgreSQL via EF6, EF6.npgsql et npgsql.

    D'abord à l'ouverture de l'application, avec EF la durée de connexion est tellement longue (plus de 6 sec) que j'avais moi-même tendance à vouloir cliquer plusieurs fois pour redémarrer l'appli. Donc l'utilisateur pensera aussi que ça a planté. J'ai donc dû ajouter un splashscreen.
    Mais j'ai lu à quelques endroits qu'avec EF la première connexion est effectivement très lente.
    Ensuite, une fois la première connexion passée, je trouve que le chargement d'une table est aussi très long.
    Alors j'ai décidé de comparer.
    Et les résultats sont édifiants. Il y a bel et bien une différence avec ou sans EF. Et pas une petite différence.
    J'ai fais 3 tests :
    1 : EF + requête linq : durée 08 sec 6717041
    2 : EF + requête SQL : durée 09 sec 7228367
    3 : connexion "standard" + requête SQL : Durée1 sec 1965210

    On est quand-même dans un rapport 1/8. C'est énorme.

    Le code du test
    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
                TimeSpan duree1;
                TimeSpan duree2;
                TimeSpan duree3;
                var sqlStr = @"SELECT DISTINCT greffe.personnes.* "
                            + "FROM greffe.personnes "
                            + "JOIN greffe.minutes_proprietaires ON greffe.minutes_proprietaires.id_personne = greffe.personnes.id_personne "
                            + "ORDER BY greffe.personnes.nom, greffe.personnes.prenom";
                try
                {
                    DateTime deb1 = DateTime.Now;
                    using (var ctr = new GreffeAdoModelContainer())
                    {
                        var result = ctr.personnes.Include("minutes").Where(p => p.minutes.Any()).ToList();
                        Proprietaires = new ObservableCollection<personnes>(result);
                    }
                    duree1 = DateTime.Now - deb1;
     
     
                    DateTime deb2 = DateTime.Now;
                    using (var ctr = new GreffeAdoModelContainer())
                    {
                        var test = ctr.personnes.SqlQuery(sqlStr).ToList();
                    }
                    duree2 = DateTime.Now - deb1;
     
     
                    DateTime deb3 = DateTime.Now;
                    ObservableCollection<personnes> testObs = new ObservableCollection<personnes>();
                    using (var conn = new Npgsql.NpgsqlConnection(cs))
                    {
                        conn.Open();
                        using (var cmd = new Npgsql.NpgsqlCommand(sqlStr, conn))
                        {
                            using (var dataReader = cmd.ExecuteReader())
                            {
                                while (dataReader.Read())
                                {
                                    if (dataReader != null)
                                    {
                                        personnes newPersonne = new personnes();
                                        newPersonne.id_personne = (int)dataReader["id_personne"];
                                        newPersonne.nom = dataReader["nom"].ToString();
                                        newPersonne.prenom = dataReader["prenom"].ToString();
                                        testObs.Add(newPersonne);
                                    }
                                }
                            }
                        }
                    }
                    duree3 = DateTime.Now - deb3;
                }
                catch (Exception ex)
                {
     
     
                }
    Et je rappelle les résultats : Duree1 = {00:00:08.6717041}, Duree2 = {00:00:09.7228367} et Duree3 = {00:00:01.1965210}
    Je me dis que c'est pratiquement impossible qu'il y ait une telle différence et qu'en EF, même si je ne vois pas comment, je devrais peut-être requeter autrement parce qu'EF a l'air intéressant, mais avec des rendements pareils, je crois qu'il vaut mieux que je recode tout en "standard".
    Qqn a-t-il une explication pour cette lenteur (et donc pour l'accélérer. Parce que +/-8 secondes à chaque ouverture de UserControl c'est plus que très long) ?
    Il n'y a pas de problèmes. Il n'y a que des solutions.
    Malheureusement, elles sont parfois un peu dur à trouver ...


    Aucune touche n'a été maltraitée pour réaliser ce texte.

  2. #2
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2007
    Messages
    871
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Février 2007
    Messages : 871
    Points : 1 498
    Points
    1 498
    Par défaut
    Bonjour,


    Dans le premier test (EF) tu fais un include, alors que dans ta requete SQL tu ne fais pas de sous select, il faudrais donc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ctr.personnes.Where(p => p.minutes.Any()).ToList();
    De plus il manque le distinct et le order by.

    Dans le second test, tu fais la mesure avec deb1 et non deb2.

    voila qui explique pas mal les differences.

    Dernier points (mais qui impactent pas vraiment les perfs) :
    - on utilise generalement la classe stopwatch pour mesure les perfs.
    - EF et la bdd creent du cache, donc il faut fais des mesures en masse
    - le second test de ne cree pas de observable collection

  3. #3
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 122
    Points
    122
    Par défaut
    Merci de tes remarques toujours pertinentes mermich.

    Effectivement dans le 1 il n'y a ni le distinct ni le OrderBy. Mais il me semble ça allongerait encore le délai. Donc même si de toute manière je devrai ajouter au moins le OrderBy, le délai ne raccourcirait pas.
    Aussi, je n'ai pas mis de distinct dans le linq parce que je pensais que de la manière dont j'avais écris le linq, il ne sortait qu'une seule fois chaque personne qui a au moins une minute. Ce qui semblait se vérifier puisque le nombre de personnes sorties est le même dans les 3 tests.

    Autre erreur de ma part : en effet j'ai bien fais la diff sur deb1 au lieu de deb2. Et quand je fais la bonne diff, j'obtiens un délai sensiblement identique pour les 2 requêtes en sql. Ce qui confirme
    Dans le premier test (EF) tu fais un include, alors que dans ta requete SQL tu ne fais pas de sous select
    Alors si l'include n'est pas la bonne solution (ce que je peux très bien concevoir et qui semble se vérifier vu le délai du linq comparé aux délais des requêtes en sql), comment faudrait-il faire en linq pour sortir dans un délai raisonnable les propriétaire qui sont liés à au moins une minute (Parce qu'après tout, c'est ça le but de ma recherche) ?
    Il n'y a pas de problèmes. Il n'y a que des solutions.
    Malheureusement, elles sont parfois un peu dur à trouver ...


    Aucune touche n'a été maltraitée pour réaliser ce texte.

  4. #4
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2007
    Messages
    871
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Février 2007
    Messages : 871
    Points : 1 498
    Points
    1 498
    Par défaut
    Alors si l'include n'est pas la bonne solution (ce que je peux très bien concevoir et qui semble se vérifier vu le délai du linq comparé aux délais des requêtes en sql), comment faudrait-il faire en linq pour sortir dans un délai raisonnable les propriétaire qui sont liés à au moins une minute (Parce qu'après tout, c'est ça le but de ma recherche) ?
    Alors il faut distinguer 2 choses: fitrer les donnees, et construire un resultat qui contient plusieures tables.
    Grosso modo en sql ne pas confondre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select *from matable where matable.id in(select id from table2)
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select * from matable,table2 where matable.id= table2.id
    le premier cas c'est juste filterr les donnes(oui je sais un exist est plus rapide), dans le second cas c'est une jointure complete.

    Dans mon message precedent je t'ai indique comment filtrer sans pour autant inclure la seconde table.

  5. #5
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 122
    Points
    122
    Par défaut
    Ok, je vois ce que je n'avais pas saisi.
    Mon erreur est que je pensais que pour lire les données de la table minutes, je devais forcément l'inclure.
    Mais là je comprend que je peux filtrer sans "charger".
    En fait c'est mon include qui était de trop et qui ralentissait tout.

    Merci bcp. J'apprend, j'apprend.
    Il n'y a pas de problèmes. Il n'y a que des solutions.
    Malheureusement, elles sont parfois un peu dur à trouver ...


    Aucune touche n'a été maltraitée pour réaliser ce texte.

  6. #6
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 122
    Points
    122
    Par défaut
    J'ai toutefois encore des problèmes de rapidité au chargement de tables. Mais je peux comprendre et admettre que le pbl soit de mon côté. Auquel cas, qu'est-ce que je fais mal ?

    J'ai fais une classe static pour faire des test et écris ça pour comparer la rapidité de chargement d'une table PostgreSQL qui contient 20498 lignes (ce qui est loin d'être énorme) :
    Et pour tenter de comparer ce qui est comparable, j'ai récupéré la string générée par EF pour context.personnes et j'ai fait une connexion npgsql avec la même requête.
    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
           public static void TestLoadPersonnes()
            {
                TimeSpan delaiEF;
                TimeSpan delaiNpgsql;
                Stopwatch swEF = new Stopwatch();
                Stopwatch swNpgsql = new Stopwatch();
                try
                {
                    swEF.Start();
                    using (var context = new AdoModelContainer())
                    {
                        var result = context.personnes.ToList();
                    }
                    swEF.Stop();
     
     
                    swNpgsql.Start();
                    using (var con = new NpgsqlConnection(cs))
                    {
                        con.Open();
                        //SQL générée par context.personnes.ToString() :
                        //SELECT "Extent1"."id_personne", "Extent1"."nom", "Extent1"."prenom", "Extent1"."nom_contact", "Extent1"."prenom_contact", "Extent1"."no_civique", "Extent1"."rue", "Extent1"."ville", "Extent1"."cp", "Extent1"."tel_res", "Extent1"."tel_trav", "Extent1"."poste_trav", "Extent1"."cell", "Extent1"."courriel", "Extent1"."actif", "Extent1"."date_maj", "Extent1"."province", "Extent1"."pays", "Extent1"."id_vision" FROM "personnes" AS "Extent1"
                        string sql = "SELECT Extent1.id_personne, Extent1.nom, Extent1.prenom, Extent1.nom_contact, Extent1.prenom_contact, Extent1.no_civique, Extent1.rue, Extent1.ville, Extent1.cp, Extent1.tel_res, Extent1.tel_trav, Extent1.poste_trav, Extent1.cell, Extent1.courriel, Extent1.actif, Extent1.date_maj, Extent1.province, Extent1.pays, Extent1.id_vision FROM personnes AS Extent1";
                        List<personnes> testLst = new List<personnes>();
                        using (var cmd = new NpgsqlCommand(sql, con))
                        {
                            using (NpgsqlDataReader rdr = cmd.ExecuteReader())
                                while (rdr.Read())
                                {
                                    personnes pers = new personnes();
                                    pers.id_personne = (int)rdr["id_personne"];
                                    pers.nom = (string)rdr["nom"];
                                    pers.prenom = (rdr["prenom"] is DBNull) ? null : (string)rdr["prenom"];
                                    pers.nom_contact = (rdr["nom_contact"] is DBNull) ? null : (string)rdr["nom_contact"];
                                    pers.prenom_contact = (rdr["prenom_contact"] is DBNull) ? null : (string)rdr["prenom_contact"];
                                    pers.no_civique = (rdr["no_civique"] is DBNull) ? null : (string)rdr["no_civique"];
                                    pers.rue = (rdr["rue"] is DBNull) ? null : (string)rdr["rue"];
                                    pers.ville = (rdr["ville"] is DBNull) ? null : (string)rdr["ville"];
                                    pers.cp = (rdr["cp"] is DBNull) ? null : (string)rdr["cp"];
                                    pers.tel_res = (rdr["tel_res"] is DBNull) ? null : (string)rdr["tel_res"];
                                    pers.tel_trav = (rdr["tel_trav"] is DBNull) ? null : (string)rdr["tel_trav"];
                                    pers.poste_trav = (rdr["poste_trav"] is DBNull) ? null : (string)rdr["poste_trav"];
                                    pers.cell = (rdr["cell"] is DBNull) ? null : (string)rdr["cell"];
                                    pers.courriel = (rdr["courriel"] is DBNull) ? null : (string)rdr["courriel"];
                                    pers.actif = (rdr["actif"] is DBNull) ? null : (bool?)rdr["actif"];
                                    pers.date_maj = (rdr["date_maj"] is DBNull) ? null : (DateTime?)rdr["date_maj"];
                                    pers.province = (rdr["province"] is DBNull) ? null : (string)rdr["province"];
                                    pers.pays = (rdr["pays"] is DBNull) ? null : (string)rdr["pays"];
                                    pers.id_vision = (rdr["id_vision"] is DBNull) ? null : (int?)rdr["id_vision"];
                                    testLst.Add(pers);
                                }
                        }
                    }
                     swNpgsql.Stop();
     
     
                    delaiEF = swEF.Elapsed;
                    delaiNpgsql = swNpgsql.Elapsed;
                }
                catch (Exception ex) { MessageBox.Show("erreur : " + ex.Message, "erreur", MessageBoxButton.OK, MessageBoxImage.Error); }
            }
    delaiNpgsql me donne une valeur de {00:00:00.4195543}
    delaiEF me donne une valeur de {00:00:03.3105785}

    En faisant le test plusieurs fois, le délai est toujours entre 6 et 8 fois supérieur avec EF.
    Et cette fois il ne me semble pas que mon test soit mauvais. Je teste exactement la même requête et j'ai le start et le stop du stopWatch à la même place pour les 2 versions.
    Vu que via PgAdmin (la plate-forme d'administration la plus souvent utilisée avec PostgreSQL) la même requête me retourne le résultat en 403 ms, le délai de ma connexion via npgsql semble correct.
    Donc, qu'est-ce que je fais de mal pour avoir ce délai avec EF ?
    Comment dois-je faire pour avoir des délais plus raisonnables avec EF ?

    Merci de vos avis, et surtout de vos explications.
    Il n'y a pas de problèmes. Il n'y a que des solutions.
    Malheureusement, elles sont parfois un peu dur à trouver ...


    Aucune touche n'a été maltraitée pour réaliser ce texte.

  7. #7
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    avis à prendre avec des pincettes car je ne l'ai jamais vraiment utilisé, enfin pas en prod
    mais à priori tous les experts que j'ai croisé ici et là sont unanimes, EF c'est lent et c'est pour les pas pros en sql ou les petits projets ...

    après sur un select simple d'une table ca m'étonne quand même une telle différence, surtout qu'EF a évolué et n'est plus censé être la catastrophe qu'il était au début (surtout en .net core)



    pour les mesures de temps les biais à éviter sont :
    - temps d'exécution d'une méthode .net plus long la 1ère fois car compilation de celle ci
    - temps d'exécution d'une requete plus rapide la 2ème fois car données en ram
    mais tu sembles les avoir éviter...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  8. #8
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 122
    Points
    122
    Par défaut
    Merci de ces infos Pol.




    J'admets que j'ai été attiré par le fait que EF fait quand-même une grosse partie du boulot tout seul.
    C'est vrai qu'écrire ceci est plus facile et surtout bcp plus rapide que de faire les classes et les requêtes à la main (surtout qu'il y a encore d'autres tables )
    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
    result = ctr.minutes
                                        .Include("ags")
                                        .Include("dossiers")
                                        .Include("operations")
                                        .Include("personnes")
                                        .Include("minutes_nouv_lots")
                                        .Include("minutes_nouv_lots.nouv_lots")
                                        .Include("minutes_anc_lots")
                                        .Include("minutes_anc_lots.anc_lots")
                                        .Include("minutes_carnets")
                                        .Include("minutes_carnets.carnets")
                                        .Where(m => m.minutes_anc_lots.Any(minutes_anc_lot => minutes_anc_lot.anc_lots.code_cad == SelectedCad.Code
                                                                                               && minutes_anc_lot.anc_lots.code_ds == SelectedDesSec.Code
                                                                                               && minutes_anc_lot.anc_lots.no_lot.CompareTo(ALotFrom) >= 0
                                                                                               && minutes_anc_lot.anc_lots.no_lot.CompareTo(ALotTo + "%") <= 0)).ToList();
    surtout quand lesdites minutes doivent être triturées dans tous les sens et que, paradoxalement, cette requête ne prend pas plus de temps que la lecture d'une table seule.




    Toutefois je suis encore tombé dans l'écueil du premier chargement. En effet la première itération de la requête est est très longue mais les suivantes sont bcp plus semblables à npgsql.
    Mon erreur étant de redémarrer le proj entre chaque mesure. Donc j'ai chaque fois un premier chargement.
    Donc au lien de redémarrer, pour tester, j'ai mis successivement plusieurs fois la même tâche. Et là j'arrive à des temps bien plus courts au second passage, et à des temps semblables à npgsql à partir du 3ème passage. Néanmoins, pour certaines tables, et toujours en lecture de la table seule et complète (type select * from ...) j'ai encore des temps passablement plus longs.

    Mais malheureusement ça ne règle pas le problème pour lequel j'avais fait ces tests.
    En fait mon problème est que j'ai plusieurs UserControls avec des combobox à alimenter à l'ouverture de l'application. Le faire au chargement du userControl est vraiment très long (j'ai moi-même envie de recliquer sur le bouton de lancement du userControl pcq j'ai l'impression que ce n'est pas passé. Alors imagine l'utilisateur lambda qui ne sait pas et ne comprend pas pourquoi c'est si long ...). Donc je me suis dit que je ferais un chargement global et en async de toutes les listes qui alimentent les combobox. Et pendant ce temps là, j'affiche un splashscreen. Mais quand je tourne autour des 20-25 secondes de splashscreen, je continue de trouver ça très long.
    Est-ce que qqn qui doit charger des tables via EF au départ d'une appli a une solution plus rapide que la mienne ?
    Il n'y a pas de problèmes. Il n'y a que des solutions.
    Malheureusement, elles sont parfois un peu dur à trouver ...


    Aucune touche n'a été maltraitée pour réaliser ce texte.

  9. #9
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2007
    Messages
    871
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Février 2007
    Messages : 871
    Points : 1 498
    Points
    1 498
    Par défaut
    Alors pour ou contre ef c'est un faux debat.

    Il est vrai qu'EF sera toujours plus lent qu'un truc ecris a la main. Mais EF n'est pas juste un outils pour faire des requetes c'est un ORM avec gestion d'etats de transactions ect. Si tu veux un truc plus rapide tu peux par exemple utiliser un microORM comme dapper.

    Enfin, pour ton soucis de chargement, une vue calculee et des index correctement mis ameliorerai considerablement les choses.

  10. #10
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 122
    Points
    122
    Par défaut
    Citation Envoyé par mermich Voir le message
    Enfin, pour ton soucis de chargement, une vue calculee et des index correctement mis ameliorerai considerablement les choses.
    Je comprend et j'ai justement des vues pour les moments où je ne charge pas la table en entier. Et ce que je charge sont de "simples" "select * from table" ou "select * from vue". Je ne vois pas quelle vue pourrait accélérer ça.
    Malheureusement le premier chargement reste très lent (à mon impression personnelle).

    J'essaye EF parce que, je l'admets aisément, c'est bien plus simple si les requêtes update/insert sont déjà faites et si les transactions sont gérés (surtout qu'avec les tables intermédiaires, ça fait vite bcp de requêtes à écrire et donc de temps qu'on peut gagner).
    Mais je ne connaissais pas microORM dapper. Je vais aller voir ça. Merci.
    Il n'y a pas de problèmes. Il n'y a que des solutions.
    Malheureusement, elles sont parfois un peu dur à trouver ...


    Aucune touche n'a été maltraitée pour réaliser ce texte.

  11. #11
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2007
    Messages
    871
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Février 2007
    Messages : 871
    Points : 1 498
    Points
    1 498
    Par défaut
    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
    result = ctr.minutes
                                        .Include("ags")
                                        .Include("dossiers")
                                        .Include("operations")
                                        .Include("personnes")
                                        .Include("minutes_nouv_lots")
                                        .Include("minutes_nouv_lots.nouv_lots")
                                        .Include("minutes_anc_lots")
                                        .Include("minutes_anc_lots.anc_lots")
                                        .Include("minutes_carnets")
                                        .Include("minutes_carnets.carnets")
                                        .Where(m => m.minutes_anc_lots.Any(minutes_anc_lot => minutes_anc_lot.anc_lots.code_cad == SelectedCad.Code
                                                                                               && minutes_anc_lot.anc_lots.code_ds == SelectedDesSec.Code
                                                                                               && minutes_anc_lot.anc_lots.no_lot.CompareTo(ALotFrom) >= 0
                                                                                               && minutes_anc_lot.anc_lots.no_lot.CompareTo(ALotTo + "%") <= 0)).ToList();
    C'est pas 'juste' un select, c'est un select * sur 11 tables, avec un where tres discutable.
    Donc cree une vue materialisee qui reprends ces 11 tables ce serai sans doute bien. Cree les index qui vont bien partout aussi.

  12. #12
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 122
    Points
    122
    Par défaut
    En effet cette requête n'est "pas 'juste' un select, c'est un select * sur 11 tables", mais cette requête était un exemple que je donnais pour dire pourquoi j'ai tenté EF. Parce qu'en effet, cette requête est bien plus rapide à écrire de la sorte.
    Quant à "
    avec un where tres discutable.", je veux bien l'admettre. Mais sachant que la table maitresse (minutes) est liée à la table anc_lots via la table minutes_anc_lots (qui ne contient pas que les id, donc pas de many to many direct), comment trouver et charger toutes les minutes qui contiennent les anciens lots qui ont un code_cad, un code_ds et un no_lot particuliers si ce n'est pas un where ?
    Ceci dit, cette requête n'était pas le sujet de mon post puisque cette requête fonctionne très bien et relativement rapidement une fois que toutes les tables ont été chargées au moins une fois et que EF a donc fait son cache.
    Je me demandais pourquoi il faut 8 secondes pour lire un simple sélect sur une table contenant +/- 20.000 lignes. Je comprend que la première lecture soit plus lente puisqu'il fait son cache qu'il utilisera aux lectures suivantes. Mais entre 0.6 sec et 8 sec, on s'entend qu'il y a un facteur supérieur à 10. Je pensais (peut-être naïvement) que la création d'un cache ne nécessiterait pas un temps 10 fois plus long.
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public static async Task<List<personnes>> ExtractPersonnesAsync()
            {
                try
                {
                    using (var context = new GreffeAdoModelContainer())
                    {
                        var result = await context.personnes.ToListAsync();
                        return result;
                    }
                }
                catch { return null; }
     
            }

    temps de lecture à l'ouverture : 7.8 sec. Les lectures suivantes sont sont à une vitesse raisonnable (autour de 0.6 à 0.8 sec), mais quand on ouvre l'application, on s'entend que l'utilisateur lambda qui doit attendre 8 sec se demande ce qu'il se passe.
    Mais j'ai fini par trouver une solution.
    Je charge d'abord toutes les tables dont j'ai besoin au démarrage sans EF. Et en parallèle je fais un premier chargement de toutes mes tables via EF afin que le tampon se crée. Ensuite je continue avec EF pour les requêtes qui nécessitent des appels à bcp de tables, comme l'exemple ci dessus.
    Il n'y a pas de problèmes. Il n'y a que des solutions.
    Malheureusement, elles sont parfois un peu dur à trouver ...


    Aucune touche n'a été maltraitée pour réaliser ce texte.

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

Discussions similaires

  1. [Apache] Différence URL avec ou sans ":80"
    Par sylk974 dans le forum Apache
    Réponses: 2
    Dernier message: 11/12/2005, 15h14
  2. [CSS][HTML] Mise en page : Avec ou sans tableaux ?
    Par arno2000 dans le forum Mise en page CSS
    Réponses: 4
    Dernier message: 09/08/2005, 02h34
  3. Réponses: 7
    Dernier message: 23/07/2005, 12h50
  4. Saut avec ou sans condition
    Par Frenchghost dans le forum Assembleur
    Réponses: 16
    Dernier message: 03/01/2005, 13h28
  5. [C#] [EXCEL] Travailler avec EXCEL sans ouvrir le logiciel
    Par Fabsou dans le forum Windows Forms
    Réponses: 3
    Dernier message: 16/07/2004, 10h29

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