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 :

[CORE] Problèmes d'inclusion ?


Sujet :

Entity Framework

  1. #1
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut [CORE] Problèmes d'inclusion ?
    Bonjour à tous.

    Je me tourne vers vers car je suis totalement perdu. J'avoue être assez nouveau avec Entity Framework Core qui l'est beaucoup moins est tout aussi perplexe que moi devant ce phénomène.

    Voici le problème (en schématisant)...

    Nous avons une classe A qui possède toute une ribambelle de propriété de navigations. C'est un peu la classe centrale du projet.

    Dans une méthode GetListOfA() (qui renvoie donc une liste d'objets de type A), suivant qu'on ajoute un where ou non sur le IQueryable défini en début de méthode, il y a une liste qui n'est pas chargée.

    Mon confrère a fait des tests hier et on arrive à des choses en plus bizarre.

    Il a mis un breakpoint avait le where qui pose problème (en fait, je crois directement après la définition du IQueryable et de tous ses Includes) et il a placé un quickwatch sur l'instance du IQueryable.
    Sur ce quickwatch, il fait un First() et reçoit bien en réponse un object avec toutes ses listes incluses chargées correctement.
    Il recommence, refait un quickwatch mais là, il fait un ToList(). Il reçoit bien une liste d'objets avec toutes les listes incluses chargées sauf une.
    Dernier test, toujours avec un quickwatch au même endroit. Il faut d'abord le First() puis ensuite, sur le même quickwatch (ie dans la même exécution), il demande le ToList(). Et là, le premier a bien la liste qui fait défaut habituellement mais pas les autres.

    Auriez-vous une idée de ce qui pourrait cause ce problème ?

    Notre version d'Entity Framework Core est 2.2.6 et le projet est en Asp.NET Core 2.2.
    Kropernic

  2. #2
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 2 065
    Points : 4 229
    Points
    4 229
    Par défaut
    Tu peux utiliser include pour charger les sous objets
    https://docs.microsoft.com/fr-fr/ef/...g/related-data

  3. #3
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Tous les .Include() nécessaires sont bien là (c'est pour ça que je parlais de "liste incluses" dans mon message initial).

    Je posterai bien du code pour que ce soit plus clair mais je ne sais pas trop si j'ai le droit...

    J'vais en remplaçant tous les noms... Ca va être moche mais bon...

    *5 minutes plus tard*

    Voici le code expurgé :
    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
     public async Task<List<MyObject>> GetMyObjectsAsync(GetObjectParams criteria){
    	IQueryable<MyObject> myObjectsQuery = this.dbContext.MyObjects
    		.Include(o => o.PropA)
    		.Include(o => o.PropB)
    		.Include(o => o.PropC)
    		.Include(o => o.PropD)
    		.Include(o => o.PropE)
    			.ThenInclude(propE => propE.PropX)
    		.Include(o => o.PropF)
    			.ThenInclude(propF => propF.PropY)
    		.Include(o => o.PropG);
     
     
    	if (criteria.XXXX.HasValue)
    	{
    		myObjectsQuery = myObjectsQuery.Where(t => t.XXXX == criteria.XXXX);
    	}
     
     
    	if (another criteria)
    	{
    		myObjectsQuery = myObjectsQuery.Where(la clause where qui va bien);
    	}
     
    	// plein d'autre tests sur différents critères qui peuvent être présent ou non dans le paramètre reçu en entrée de la fonction.
     
     
    	List<MyObject> myObjects = await myObjectsQuery.ToListAsync();
     
     
    	return myObjects;
    }
    Et c'est en fait le PropD (ça aide hein ? ) qui ne se remplit pas tout le temps. Je précise que cette propriété n'est pas une objet unique mais une liste d'objets. Mais ce n'est pas la seule dans le cas donc j'vois pourquoi ce serait ça le noeud du problème mais j'préfère préciser au cas où.

    Au cours de mes tests, j'ai pu détecter que ce problème survient quand le code passe dans un if bien précis. Dans ce if, il y a un test spatial qui est fait (utilisation de SqlGeography) dans la méthode d'extension Where. Si l'exécution ne passe pas sur ce point, alors tout est bien rempli.
    Kropernic

  4. #4
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 2 065
    Points : 4 229
    Points
    4 229
    Par défaut
    Tu peux logger les requêtes générés https://docs.microsoft.com/fr-fr/ef/...ogging?tabs=v3
    Crois moi tu peux avoir des sacrés surprise parfois avec EF

    Utilises tu un Predicate Builder ou chaine tu les where dans des if à chaque fois, et il faut modéliser parfois ces requêtes comme si tu écrivais du T-SQL, pour la spatialisation j'y connais pas grand chose, jamais utilisé cette fonctionnalité de SQL Server.

  5. #5
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Ca tourne sur Azure donc je vois déjà les requêtes générées. C'est assez dingue effectivement. Ca me donne l'impression qu'il fait une dizaine de requête différentes puis qu'il rassemble tout de son côté.

    Il n'y a pas de Predicate Builder. C'est effectivement une succession de if avec chaque fois la variable de type IQueryable qui reçoit le résultat du Where.

    Si ça ne tenait qu'à moi, je ferais une procédure stockée mais ça n'est pas le cas ^^.
    Kropernic

  6. #6
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 2 065
    Points : 4 229
    Points
    4 229
    Par défaut
    Citation Envoyé par Kropernic Voir le message
    Ca tourne sur Azure donc je vois déjà les requêtes générées. C'est assez dingue effectivement. Ca me donne l'impression qu'il fait une dizaine de requête différentes puis qu'il rassemble tout de son côté.

    Il n'y a pas de Predicate Builder. C'est effectivement une succession de if avec chaque fois la variable de type IQueryable qui reçoit le résultat du Where.

    Si ça ne tenait qu'à moi, je ferais une procédure stockée mais ça n'est pas le cas ^^.
    Dans certains cas une vue peut être pas mal aussi, surtout que tu peux la binder a une entité et l'utiliser avec EF comme si c'était une table classique.

    A ta place je jouerais juste sur ce where qui fout le bordel et désactiverais les autres pour voir ce qu'il se passe peut être la condition a l'intérieur n'est pas facilement interprétable par EF, et tu peux avoir des fonctions dédiés.
    https://docs.microsoft.com/fr-fr/ef/...deling/spatial

  7. #7
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    C'est EF Core 2.2. L'utilisation des vues n'est pas disponibles . Si j'ai bien lu, c'est dispo dans la version 3 mais ça demanderait pas mal de changement.

    Quoi qu'il en soit, je ne vois pas en quoi une vue pourrait m'aider dans le cas présent. Tu pourrais détailler stp ?

    Ta dernière remarque m'a mis le doute quant au fait de savoir si les requêtes spatiales sont acceptés en 2.2 mais ça fonctionnait avant ma dernière release en UAT donc ça doit pas être ça. Dernière release qui ne touchait pas à cette méthode bien sûr. Sinon c'est trop simple à débugguer...
    Kropernic

  8. #8
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    J'ai eu l'autorisation de poster du code (nouveau dans cette boîte, je préférais demander d'abord) donc voici une petite mise à jour qui sera je pense beaucoup plus explicite du coup.

    Voici donc le code de la méthode qui pose problème :
    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
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
            public async Task<List<Tool>> GetToolsAsync(GetToolParams criteria)        {
                IQueryable<Tool> tools = this.dbContext.Tools
                    .Include(t => t.Type)
                    .Include(t => t.ToolStatus)
                    .Include(t => t.AssignedUsers)
                    .Include(t => t.Tag)
                    .Include(t => t.Inspections)
                    .Include(t => t.Groups)
                        .ThenInclude(g => g.Group)
                    .Include(t => t.Sites)
                        .ThenInclude(s => s.Site);
     
     
                if (criteria.Latitude != null && criteria.Longitude != null && criteria.Distance != null)
                {
                    SqlGeography point = SqlGeography.Point(criteria.Latitude.Value, criteria.Longitude.Value, 4326);
                    SqlGeography surrounding = point.BufferWithTolerance(criteria.Distance.Value, 0.01, true);
     
     
                    tools = tools.Where(t => t.CurrentPosition != null && (t.CurrentPosition.STIntersects(surrounding) ? true : false));
                }
     
     
                if (criteria.CompanyId.HasValue)
                {
                    tools = tools.Where(t => t.CompanyId == criteria.CompanyId);
                }
     
     
                if (criteria.UserType != null && criteria.UserType.Equals("worker", StringComparison.InvariantCultureIgnoreCase))
                {
                    // TODO refaire le filtre sans faire 2 fois le orderBy
                    // Utiliser un ForEach?
                    tools = tools.Where(t => t.ToolStatus.OrderByDescending(ts => ts.ValidationDate).FirstOrDefault().Status != (int)ToolStatus.Broken && t.ToolStatus.OrderByDescending(ts => ts.ValidationDate).FirstOrDefault().Status != (int)ToolStatus.OutOfStock);
                }
     
     
                if (criteria.AssignedUserId.HasValue)
                {
                    tools = tools.Where(t => t.AssignedUsers.OrderByDescending(s => s.ValidationDate).FirstOrDefault().UserId == criteria.AssignedUserId);
                }
     
     
                if (criteria.SiteId.HasValue)
                {
                    tools = tools.Where(
                        t => t.Sites
                        .OrderByDescending(ts => ts.ValidationDate)
                        .Any(ts => ts.IsCurrentAssignedSite && ts.SiteId == criteria.SiteId.Value));
                }
     
     
                if (criteria.HasTag.HasValue && criteria.HasTag.Value)
                {
                    tools = tools.Where(t => t.Tag.Any(ta => ta.Enabled));
                }
     
     
                List<Tool> toolsList = await tools.ToListAsync();
     
     
                foreach (Tool tool in toolsList)
                {
                    if (tool.Sites != null)
                    {
                        tool.AssignedSite = tool.Sites.SingleOrDefault(s => s.SiteLocationType == SiteLocationType.Assigned)?.Site;
                        tool.CurrentSite = tool.Sites.SingleOrDefault(s => s.IsCurrentAssignedSite)?.Site;
                    }
     
     
                    if (tool.AssignedUsers != null && tool.AssignedUsers.Count > 0)
                    {
                        tool.CurrentAssignedUserId = tool.AssignedUsers.SingleOrDefault(x => x.IsCurrentAssignedUser)?.UserId;
                    }
                }
     
     
                return toolsList;
            }
    Tout fonctionne très bien SAUF si on rentre dans le premier IF pour faire une analyse spatiale.

    Quant à mon message précédent où j'écrivais que cela fonctionnait avant ma dernière release en UAT, c'est en fait faux. J'ai ce matin créé une nouvelle branche basée sur celle d'uat et je me suis "amusé" à faire un revert de chaque commit jusqu'à la dernière release. Le problème est le même sauf qu'on ne le voyait pas car le calcul dans le get de la propriété InspectionExpired de l'outil (pour savoir donc s'il en retard d'inspection) était fait "à l'envers" (je pourrais détailler si nécessaire).

    Donc voilà. Pourquoi les inspections sont-elles manquantes en cas de requête spatiale ?

    N.B. : Entre temps, j'ai pu reproduire les tests fait par mon confrère (j'avais un problème de chargement de dll jusqu'ici).
    Kropernic

  9. #9
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Si j'ai bien compris, il faudrait utiliser une NetTopologySuite car sinon, Entity Framework Core ne supporterait pas les requêtes spatiales... Ceci expliquerait tout.

    Tests en cours...
    Kropernic

  10. #10
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 2 065
    Points : 4 229
    Points
    4 229
    Par défaut
    Ils utilisent cette librairie :
    https://docs.microsoft.com/fr-fr/ef/...deling/spatial
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    optionsBuilder.UseSqlServer(
        @"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=WideWorldImporters",
        x => x.UseNetTopologySuite());
    En espérant que ça résous ton soucis

  11. #11
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Oui j'ai vu. Suis en train de regarder à ça.

    Mais bien sûr, cette librairie ne gère que les type Geometry et pas les Geography... C'est génial .

    Qu'est-ce que ça me gave tous ces développeurs qui se ruent sur ces nouvelles technologies qui ne sont pas matures/finies. Avec du .NET pas core, il n'y aurait pas ce souci...
    Kropernic

Discussions similaires

  1. [JSTL] [JSF] Problème d'inclusion de la taglib core
    Par Gnarik dans le forum Taglibs
    Réponses: 14
    Dernier message: 10/12/2010, 15h47
  2. Problème d'inclusions multiples
    Par Le Furet dans le forum C
    Réponses: 2
    Dernier message: 03/10/2005, 23h59
  3. Problème d'inclusion de pages.
    Par julien85 dans le forum XML/XSL et SOAP
    Réponses: 6
    Dernier message: 01/05/2005, 18h06
  4. [Core]Problème au démarrage eclipse...
    Par SpeCiE dans le forum Eclipse Java
    Réponses: 4
    Dernier message: 01/07/2004, 09h23
  5. Problème d'inclusion
    Par degreste dans le forum MFC
    Réponses: 5
    Dernier message: 27/01/2004, 00h56

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