2010-02-11 31 views
2

je récupère une collection avec la requête suivante:Entity Framework: pourquoi les propriétés de navigation disparaissent-elles après un groupe?

var numbers = _betDetailItem.GetBetDetailItems().Where(betDetailItem => betDetailItem.BetDetail.Bet.DateDrawing == resultToCreate.Date && betDetailItem.BetDetail.Bet.Status == 1).Where(condition); 

Juste là, je suis en mesure d'accéder à mes propriétés de navigation et de naviguer dans les informations binded. Notez comment je les utilise pour filtrer les données. Après le regroupement des résultats, les propriétés de navigation deviennent nulles.

var grouped = numbers.GroupBy(p => p.BetDetail.Bet); 
//Iterate through the collection created by the Grouping 
foreach (IGrouping<Bet, BetDetailItem> group in grouped) 
{ 
    var details = group.Key.BetDetails; //This is what doesn't work. BetDetails is a navigation property which was accessible in the previous query. 
} 

Est-ce que je fais quelque chose de mal?

+0

Ils ne le font pas. Il se passe quelque chose d'autre ici qui n'est pas dans votre message. Essayez une simple requête contre Northwind sans tout votre code personnalisé. Si vous n'arrivez pas à faire fonctionner cela, affichez-le ici. –

+1

Pourquoi cela ne fonctionne-t-il pas comme tous les autres ORM? –

+0

Comme je l'ai dit, je pense que votre question repose sur une fausse prémisse. Avez-vous essayé ce que j'ai suggéré? –

Répondre

1

Vous confondez LINQ avec les entités et les opérations sur les objets.

C'est LINQ to Entities:

var numbers = _betDetailItem.GetBetDetailItems().Where(betDetailItem => betDetailItem.BetDetail.Bet.DateDrawing == resultToCreate.Date && betDetailItem.BetDetail.Bet.Status == 1).Where(condition); 

Alors est-ce:

var grouped = numbers.GroupBy(p => p.BetDetail.Bet); 

Ce sont des opérations d'objet:

foreach (IGrouping<Bet, BetDetailItem> group in grouped) 
{ 
    var details = group.Key.BetDetails; //This is what doesn't work. BetDetails is a navigation property which was accessible in the previous query. 
} 

Dans LINQ aux entités, il n'y a jamais besoin penser à charger des instances liées. Vous pouvez toujours vous référer à n'importe quelle propriété de n'importe quel objet. Cependant, à un certain point, vous voulez quitter le monde LINQ to Entities et entrer dans l'espace objets, car vous voulez travailler avec des instances de type BetDetail au lieu du type IQueryable<BetDetail>. Cela signifie que Entity Framework est désormais requis pour générer du code SQL afin d'extraire des données de la base de données. À ce stade, il ne neige pas quelles instances liées vous allez accéder dans votre code plus tard. Rien dans votre requête LINQ to Entities ne force le chargement du Bet associé. Donc, à moins que vous ne fassiez quelque chose pour le charger, comme le chargement anticipé, le chargement explicite ou le chargement différé d'EF 4, il ne sera pas chargé.

En utilisant le chargement paresseux (par exemple, dans Entity Framework 4, ou dans un autre ORM) fera ce code semble fonctionner, mais il sera inutilement lent, en raison du grand nombre de requêtes de base de données générées. Une meilleure solution serait d'utiliser eager loading ou projection. De cette façon, il n'y aura qu'un seul aller-retour DB.

1

Une fois que vous faites un GroupBy(), vous ne traitez avec vos entités - ils ont été ... eh bien, regroupés, de sorte que le var dans var grouped = ... est maintenant de type IEnumerable<IGrouping<.... En tant que tel, les méthodes disponibles sur les éléments de la collection grouped sont les méthodes de l'interface IGrouping<>.

Vous voudrez peut-être OrderBy() au lieu de GroupBy(), en fonction de vos besoins, ou vous devrez itérer sur deux niveaux: itérer sur chaque groupe grouped, et sur chaque membre au sein de chacun de ceux-ci.

Une fois que vous êtes à l'intérieur d'un IGrouping<> particulier, vous devriez avoir accès aux propriétés que vous recherchez.