none
[Entity Framework 6/7] [LINQ] condition 'where' inopérante RRS feed

  • Discussion générale

  • Bonsoir,

    j'essaye de réemployer le contenu de cette vidéo dans mon programme de test :

    https://mva.microsoft.com/fr-fr/training-courses/acc-der-aux-donn-es-ado-net-entity-framework-et-wcf-14238?l=A3Xs0YHfB_3300115888

    J'utilise une classe pour la nourriture 'Food' et une pour les fabriquants de nourriture 'FoodCompany'.La requête exécutée est :

    {SELECT     [Extent1].[Id] AS [Id],
         [Extent1].[Name] AS [Name],
         [Extent1].[FoodTypeId] AS [FoodTypeId],
         [Extent1].[FoodCompanyId] AS [FoodCompanyId] 
       FROM  [dbo].[Foods] AS [Extent1]   
       CROSS JOIN [dbo].[FoodCompanies] AS [Extent2]
       WHERE 3 = [Extent2].[Id]}

    A partir du code C# :

    using (GpaContext ctx = new GpaContext())
                    {
                        var querySelect = from foods in ctx.Foods
                                          from companies in ctx.FoodCompanies
                                          where companies.Id == 3
                                          select foods;
                        var result = querySelect.ToList();
    
                        Console.WriteLine("Liste de nourriture");
                        foreach (var food in result)
                        {
                            Console.WriteLine(food.Id + " " + food.Name + " Type:" + food.FoodTypeId + "," +
                                food.FoodType.Name + " Company:" + food.FoodCompanyId + "," + food.FoodCompany.Name);
                        }
                    }

    Et le contenu de la table :

    Pourtant à l'affiche, il me donne une liste de 5 résultats (donc en gros tout le contenu de la table et non pas uniquement le dernier élément. Je ne comprends pas pourquoi. La requête semble être bonne.

    Merci,

    Vincent

    dimanche 21 février 2016 19:35

Toutes les réponses

  • et même résultat en utilisant :

    var querySelect = from foods in ctx.Foods
                     from companies in ctx.FoodCompanies
                     where foods.FoodCompanyId == 3
                     select foods;

    J'ai tenté cette requête qui ne fonctionne pas :

    var querySelect = from foods in ctx.Foods
                      from companies in ctx.FoodCompanies
                      where foods.Name.StartsWith ("medium")
                      select foods;

    Par contre, celle-ci FONCTIONNE Donc un problème de from/from ?

    var querySelect = from foods in ctx.Foods
                      where foods.Name.StartsWith ("medium")
                      select foods;

    dimanche 21 février 2016 20:30
  • j'arrive à faire marcher mon code :

    var querySelect = from foods in ctx.Foods
                      join r in ctx.FoodCompanies on foods.FoodCompanyId equals r.Id
                      where foods.FoodCompanyId == 3
                      select foods;

    Donc, si j'ai bien compris, c'est parce que la liaison entre mes 2 tables n'est pas bonne. Pourtant, ça semble bon :

    qu'est ce que j'ai loupé ?

    Merci.


    dimanche 21 février 2016 21:01
  • Bonjour,

    Je pense que vous confondez ce que vous avez défini dans votre base de données et une requête.

    Dans votre base vous avez créé des relations, qui permettent au serveur SQL de valider vos données, par exemple dans votre cas un Food est lié à une FoodCompany si vous essayez d'ajouter un Food avec un ID de compagnie qui n'existe pas, le serveur retournera une erreur. Ca c'est grâce à votre relation.

    Maintenant lorsque vous faîtes une requête, c'est a vous d'indiquer les jointures que vous voulez. Ce n'est pas parce que vous avez défini une relation dans la base qu'elle sera reprise dans votre requête. En aucun cas.

    Les deux choses sont différentes et n'ont aucune incidence l'une sur l'autre.

    Donc vous faîtes exactement ce qu'il faut:

    • vous avez défini une relation dans votre base pour avoir une règle métier (un Food doit avoir une FoodCompany qui existe)
    • dans votre requête vous faîtes une jointure car vous voulez récupérer la FoodCompany qui correspond à Food

    Cordialement,


    Yan Grenier

    Merci de bien vouloir "Marquer comme réponse", les réponses qui ont répondues à votre question, et de noter les réponses que vous avez trouvé utiles.


    mercredi 24 février 2016 07:24
  • Bonjour.

    Comme à l’accoutumé c'est des explications claires et précise merci :).

    Dans mon cas, j'ai bien saisi la différence. Par contre, sur la vidéo de Sébastien Pertus, je ne vois pas ce qui diffère dans la base Northwind pour qu'il puisse écrire un triple 'from' :

    https://mva.microsoft.com/fr-fr/training-courses/acc-der-aux-donn-es-ado-net-entity-framework-et-wcf-14238?l=A3Xs0YHfB_3300115888

    Ca se passe à la minute 20. Un Employee possède une FK sur un Territory qui possède une FK sur une région.

    mercredi 24 février 2016 14:26
  • Merci :)

    Pour la vidéo MVA je ne peux pas y accéder pour le moment, soit MVA est down, soit j'ai un problème de réseau.

    Mais ce que je peux dire c'est que c'est possible de faire les requêtes via des CROSS JOIN en faisant les jointures au niveau de la condition WHERE. Mais ce n'est pas une bonne pratique si on peut le faire avec les jointures (INNER/OUTER).

    Les jointures sont généralement optimisé en utilisant les index et les statistiques du serveur. Alors que c'est pas toujours le cas avec les CROSS JOIN. Donc c'est faisable, mais non ce n'est pas recommandé :)

    Maintenant peut-être que pour cette formation le but de François Pertuis n'était pas d'optimiser ces requêtes mais de fournir un exemple rapide.

    Dernier point dont je n'ai pas parlé, dans votre cas, vous pouvez ne pas utiliser de jointure mais faire appel à "Include()" comme indiqué dans https://social.msdn.microsoft.com/Forums/fr-FR/960108ce-0802-49dc-b9a4-d31fee6f900d/entity-7-mappage-de-fk?forum=visualcsharpfr . La jointure se fera d'elle même. Bien entendu ce n'est possible que si vous avez défini votre relation dans classe de données.

    Cordialement,


    Yan Grenier

    Merci de bien vouloir "Marquer comme réponse", les réponses qui ont répondues à votre question, et de noter les réponses que vous avez trouvé utiles.

    mercredi 24 février 2016 14:44
  • sur Firefox effectivement ça veut pas passer. J'ai du switcher sur Edge pour retrouver MVA ce soir. Si on prend le PDF qui va avec la vidéo, page 8 :

    "Jointure 
    L’idée ici est de récupérer des éléments suivants une jointure SQL en utilisant la syntaxe from from :

    var query = from e in context.Employees
    from r in context.Regions
    from t in context.Territories
    where t.TerritoryDescription == "Seattle"
    select e;  
    
    Le gros avantage ici c’est qu’il est inutile de spécifier les jointures à utiliser car elles sont déjà connues par le modèle Northwind"

    Pour lui, Jointure == Cross Join? Du coup, avec le Inner/outer, je suis un peu perdu.
    Et il corrige son exemple ensuite en requête paramétrée pour les puristes. Donc, son exemple pourrait être plus qu'un exemple typique cas d'école.
    Je lui ai fait un mail la semaine dernière sur toutes ses vidéos que j'ai diffusées pour pouvoir échanger dessus mais bon, en tant qu'évangéliste technique officiel M$, il est dans des strates bien lointaines. :(
    mercredi 24 février 2016 23:59
  • Je suis surpris car généralement je trace des cross join dans ce cas. Alors plusieurs possibilités:

    • Soit la base d'exemple Northwind possède des informations supplémentaires que EF peut utiliser pour utiliser des jointures INNER/OUTER à la place
    • Soit il y a un loupé dans l'exercice :)
    • Soit il exploite les CROSS JOIN comme jointure. Ce n'est pas interdit, mais c'est déconseillé a partir du moment nous avons les instructions nécessaires pour faire des jointures INNER/OUTER. Peut-être que SQL Server optimise très bien les CROSS JOIN et que pour l'exemple il n'était pas nécessaire de faire des jointures INNER/OUTER.

    Pour le premier point je reste sceptique (mais je peux me tromper) car si je veux vraiment faire une CROSS JOIN, cela voudrais dire que EF me fait une jointure interne de lui même ! Comme je fais ma jointure croisée ? Ca ne me parait pas logique comme fonctionnement.

    Maintenant personnellement je pars du principe qu'il faut que le code soit lisible, une requête sans jointure n'est pas lisible car elle n'indique pas explicitement les relations que l'on veut utiliser. La lisibilité permet d'éviter de faire des documentations ou au moins de la réduire. 

    Cordialement,


    Yan Grenier

    Merci de bien vouloir "Marquer comme réponse", les réponses qui ont répondues à votre question, et de noter les réponses que vous avez trouvé utiles.

    jeudi 25 février 2016 08:25
  • Voilà la requête qui a été interceptée par le Profiler SQL :

    SELECT 
        [Extent1].[EmployeeID] AS [EmployeeID], 
        [Extent1].[LastName] AS [LastName], 
        [Extent1].[FirstName] AS [FirstName], 
        [Extent1].[Title] AS [Title], 
        [Extent1].[TitleOfCourtesy] AS [TitleOfCourtesy], 
        [Extent1].[BirthDate] AS [BirthDate], 
        [Extent1].[HireDate] AS [HireDate], 
        [Extent1].[Address] AS [Address], 
        [Extent1].[City] AS [City], 
        [Extent1].[Region] AS [Region], 
        [Extent1].[PostalCode] AS [PostalCode], 
        [Extent1].[Country] AS [Country], 
        [Extent1].[HomePhone] AS [HomePhone], 
        [Extent1].[Extension] AS [Extension], 
        [Extent1].[Photo] AS [Photo], 
        [Extent1].[Notes] AS [Notes], 
        [Extent1].[ReportsTo] AS [ReportsTo], 
        [Extent1].[PhotoPath] AS [PhotoPath]
        FROM   [dbo].[Employees] AS [Extent1]
        CROSS JOIN [dbo].[Regions] AS [Extent2]
        CROSS JOIN [dbo].[Territories] AS [Extent3]
        WHERE N'Seattle' = [Extent3].[TerritoryDescription]

    Donc il sait établir les relations entre les tables à partir des clés primaires/étrangères.
    Je creuse, encore et encore... dans Management Studio, la relation entre Territories et Regions par exemple, il nous sort :

    INNER JOIN : dbo.Territories.RegionID = dbo.Regions.RegionID

    vendredi 26 février 2016 22:15