2009-12-12 4 views
2

Je suis à la recherche dans un problème qui est lié à ... Join and Include in Entity FrameworkLinq, émulant rejoint, et la méthode Inclure

Fondamentalement, la requête suivante renvoie la liste des « biens » objets que l'utilisateur dispose d'autorisations en cours (ACLs) à voir.

IQueryable<Property> currPropList 
       = from p in ve.Property 
           .Include("phyAddress") 
           .Include("Contact") 
        from a in ve.ACLs 
        from u in ve.Account 
        from gj in ve.ObjectGroupJoin 
        where u.username == currUsername    // The username 
         && (a.Account.id == u.id    // The ACLs 
          && a.objType == (int)ObjectType.Group) 
         && (gj.ObjectGroup.id == a.objId  // The groups 
          && gj.objId == p.id)    // The properties 
        select p; 

La requête renvoie la liste correcte des propriétés et dans les grands travaux très bien. Mais les appels "Include" dans la requête linq ci-dessus ne chargent pas les objets. Si j'appelle "Load()" explicitement après la requête LINQ, alors les objets se chargent.

Le related SO question a suggéré qu'il peut y avoir un conflit entre l'appel "Include" et la clause where. Comment cela peut-il être le cas?

Mais en tout cas, comment puis-je restructurer cette requête pour charger les membres "phyAddress" et "Contract"? Plus précisément, je voudrais seulement charger les membres sur retourné objets, pas tous les objets "phyAddress" et "Contact" dans la base de données.

Merci. membre

Modifier

J'ai traqué la question à l'utilisation de plusieurs de clauses

Cela fonctionne ...

IQueryable<Property> currPropList 
      = from p in ve.Property 
          .Include("phyAddress") 
       select p; 

Et le "phyAddress" est chargé.

Mais cela ne fonctionne pas ...

IQueryable<Property> currPropList 
      = from p in ve.Property 
          .Include("phyAddress") 
       from a in ve.ACLs 
       select p; 

Fondamentalement, le Inclure appel est ignoré quand il y a plusieurs de clauses. Est-ce que quelqu'un sait d'un travail autour de cela?

Modifier 2

Une solution de contournement est de lancer le IQueryable comme résultat ObjectQuery et obtenir le comprennent hors de cela. Mais je voudrais empêcher le deuxième tour de la base de données, je suppose que cela provoque.

Par exemple. Cela fonctionne ....

IQueryable<Property> currPropList 
     = ((from p in ve.Property 
      from a in ve.ACLs 
      select p) as ObjectQuery<Property>).Include("phyAddress"); 

Existe-t-il un moyen de le faire avec une seule requête?

Edition 3

No deuxième requête en raison de l'exécution différée [http://blogs.msdn.com/charlie/archive/2007/12/09/deferred-execution.aspx. Donc, éditer 2 serait la solution.

+0

Il ne fait qu'une requête sql. Il n'y a pas de deuxième tour. Si vous n'êtes pas sûr, vous devriez regarder SQL Server Profiler. – LukLed

Répondre

4

Il s'agit d'un problème connu avec Inclure ... si vous faites quelque chose qui modifie la forme de la requête (c.-à-d.à partir de) puis Inclure est perdu il y a des solutions de contournement assez simple si:

  1. vous pouvez envelopper l'inclure dans la requête, voir Tip 22 - How to make include really include.
  2. ou vous pouvez obtenir tout ce dont vous avez besoin dans la clause select et laisser la correction de la relation faire le travail pour vous. à savoir

    var x = from p in ve.Property 
         from a in ve.ACLs 
         select new {p,p.phyAddress}; 
    
    var results = x.AsEnumerable().Select(p => p.p); 
    

des résultats maintenant est une énumération des entités de propriété, mais chacun a son phyAddress chargé, comme un effet secondaire de la demande initiale pour le phyAddress, et le fixup relation d'EF.