2016-04-18 1 views
2

Mon objectif est de faire un seul voyage dans la base de données et d'obtenir des commandes avec une collection enfant filtrée.Entity Framework 6.1.3: Projection - charge directement les enfants des enfants

Pour ce faire, je l'ai utilisé une projection:

using (var db = new context()) 
      { 
       var query = from o in db.Orders 
          select 
           new 
           { 
            Order = o, 
            Events = o.Events.Where(
             e => e.SomeBool 
             && e.SomeBool2 
            ), 

            EventsGroups = o.Events.Where(
             e => e.SomeBool 
             && e.SomeBool2 
            ).Select(e => e.Groups), 

           }; 
      } 

Le problème ici est que la collection des enfants, « Groupes » sur les événements, n'est pas chargé. Pour résoudre cela, je l'ai chargé comme une autre propriété "EventsGroups" dans la requête, que je peux ensuite mettre en place avec les événements après.

Ma question: Existe-t-il un moyen de charger l'enfant, "Groupes" sur "l'événement" directement, donc je n'ai pas besoin de les obtenir comme une autre propriété?

Le long des lignes de

Events = o.Events.Where(
e => e.SomeBool 
&& e.SomeBool2 
).Include(e => e.Groups), //this cannot be done this way 

Pourquoi suis-je en utilisant une projection et non le chargement impatient:

https://msdn.microsoft.com/en-us/magazine/hh205756.aspx

Filtering include items in LINQ and Entity Framework

Les classes sous-jacentes:

public class Order 
{ 
    public Order() 
    { 
     Events = new HashSet<Event>(); 
    } 

    public int Id { get; set; } 

    public virtual ICollection<Event> Events { get; set; } 
} 

public class Event 
{ 
    public Event() 
    { 
     Groups = new HashSet<Group>(); 
    } 

    public int Id { get; set; } 

    public bool SomeBool { get; set; } 

    public bool SomeBool2 { get; set; } 

    public virtual ICollection<Group> Groups { get; set; } 
} 

public class Group 
{ 
    public Group() 
    { 
     Events = new HashSet<Event>(); 
    } 

    public int Id { get; set; } 

    public string Name { get; set; } 

    public virtual ICollection<Event> Events { get; set; } 
} 
+0

pouvez-vous essayer 'o.Events.include (e => e.Groups) .Lorsque (...'? – SWilko

+0

Voulez-vous dire à l'intérieur de la projection? Je ne crois pas Inclure existe là http://imgur.com/ZOOXx0E – Archigo

+0

désolé vous avez raison Je pense que @Ivans réponse ci-dessous devrait fonctionner – SWilko

Répondre

0

Depuis Include ne peut pas être combiné avec une projection anonyme, vous devez projeter Event.Groups de la même façon que vous projetez Order.Events, par exemple en utilisant une autre projection de type anonyme:

var query = from o in db.Orders 
      select new 
      { 
       Order = o, 
       Events = (from e in o.Events 
          where e.SomeBool && e.SomeBool2 
          select new 
          { 
           Event = e, 
           Groups = e.Groups, 
          }), 
      }; 
+0

Ceci est beaucoup plus beau que ma façon de le faire, et plus facile à mettre ensemble. Je soupçonne que c'est un proche que je peux obtenir pour éviter les boucles pour construire les objets DTO à partir des objets anynomous. – Archigo

+0

Si vous avez un objet DTO, vous pouvez directement leur projeter à la place des types anonymes - EF le supporte. –

0

vous pouvez charger tout en mettant Configuration.LazyLoadingEnabled = true;, sans avoir besoin de tout comprendre, bien sûr ... perfoamnce doit mettre à l'esprit .. dépend ..

public MyDatabaseContext(string databaseName) 
     : base(databaseName) 
    { 
     Configuration.LazyLoadingEnabled = true; 
    } 
+0

Cela rompt avec mon objectif d'avoir seulement un voyage à la base de données – Archigo

0

Je crois que cela devrait fonctionner pour vous:

using (var db = new context()) 
{ 
    var query = db.Orders 
    .Include(o=>o.Events) 
    .Include(o=>o.Events.Select(e=>e.Groups)) 
    .Select(o=>new 
    { 
     Order = o, 
     Events = o.Events.Where(e => e.SomeBool && e.SomeBool2) 
    }); 
} 

sinon, cela:

using (var db = new context()) 
{ 
    var query = db.Orders 
    .Include(o=>o.Events) 
    .Include(o=>o.Events.Select(e=>e.Groups)) 
    .Select(o=>new Order 
    { 
     Id=o.Id, 
     Events = o.Events.Where(e => e.SomeBool && e.SomeBool2).ToList() 
    }); 
} 
+0

Cela n'a pas fonctionné pendant le test. Les groupes n'ont pas été chargés. Obtenir des ordres et les événements filtrés fonctionne, mais il y a juste une liste vide pour les groupes sur les événements. Les inclus ne semblent pas faire quoi que ce soit, car c'est le même résultat avec ou sans eux. – Archigo

+0

Hmm. Intéressant. Une solution simple consiste à ajouter '.ToList()' entre Include et Select. Cela fonctionnera certainement, cependant, vous récupérerez tous les enregistrements d'événements, et pas seulement ceux qui correspondent à vos conditions '.Where'. –