Comment la syntaxe D'expression de LINQ fonctionne-t-elle avec Include() pour le chargement rapide?

j'ai une requête ci-dessous, mais je veux effectuer un Include() pour charger des propriétés. Actions possède une propriété de navigation, User (Action.De l'utilisateur)

1) Ma requête de base:

from a in Actions
join u in Users on a.UserId equals u.UserId
select a

2) Première tentative:

from a in Actions.Include("User")
join u in Users on a.UserId equals u.UserId
select a

Mais L'Action.L'utilisateur est peuplée.

3) Essayez de charger 'User' dans la propriété de navigation en action en dehors de query:

(from a in Actions
join u in Users on a.UserId equals u.UserId    
select a).Include("User")

in LINQPad trying Includ's I get an erreur:

'Système.Linq.IQueryable" ne contient pas de définition pour "Include" et aucune méthode d'extension "Include" accepter un premier argument de type " Système.Linq.IQueryable ' peut être trouvé (appuyez sur F4 pour ajouter une directive d'utilisation ou une référence d'assemblage)

je pense que C'est parce que LINQ ne supporte pas Include().

alors j'ai essayé en VS; la requête 2 s'exécute, mais renvoie la propriété utilisateur non peuplée. Requête 3 la méthode d'extension ne semble pas exister, bien qu'elle existe sur l'Action elle-même sans la requête.

28
demandé sur jaffa 2011-07-20 15:23:23

5 réponses

j'ai compris, merci pour les suggestions de toute façon. La solution est de le faire (2ème tentative dans ma question):

var qry = (from a in Actions
join u in Users on a.UserId equals u.UserId    
select a).Include("User")

la raison pour laquelle intellisense ne s'est pas montré Include après la requête était parce que j'avais besoin de l'utilisation suivante:

using System.Data.Entity;

tout fonctionnait bien en faisant cela.

55
répondu jaffa 2011-07-21 13:00:56

si ce que vous voulez est une requête qui retournera tout Action entités dont les associés User entity existe réellement via le Action.UserIdpropriété de clé étrangère, cela va faire ça:

var results = context.Actions
    .Include("User")
    .Where(action =>
        context.Users.Any(user =>
            user.UserId == action.UserId));

cependant vous n'avez pas besoin d'utiliser des propriétés de clé étrangère pour faire du filtrage, puisque vous avez également propriétés de navigation. Ainsi, votre requête peut être simplifiée en filtrant sur le Action.User propriété de navigation à la place, comme dans cette exemple:

var results = context.Actions
    .Include("User")
    .Where(action => action.User != null);

si votre modèle indique que le Action.User propriété ne peut jamais être nulle (c'est à dire l' Action.UserId clé étrangère n'est pas les valeurs null dans la base de données) et ce que vous voulez est en fait tout Action entités qui leur sont associés Users, alors la requête devient encore plus simple

var results = context.Actions.Include("User");
16
répondu Enrico Campidoglio 2011-07-20 12:04:41

Mieux, refactoriser le code est adapté (EF6)

using System.Data.Entity;
[...]
var x = (from cart in context.ShoppingCarts
where table.id == 123
select cart).Include(t => t.CartItems);

ou

var x = from cart in context.ShoppingCarts.Include(nameof(ShoppingCart.CartItems))
where table.id == 123
select cart;

mise à Jour 3/31/2017

vous pouvez également utiliser la syntaxe include dans lambda pour l'une ou l'autre des méthodes:

var x = from cart in context.ShoppingCarts.Include(p => p.ShoppingCart.CartItems))
where table.id == 123
select cart;
9
répondu K0D4 2017-03-31 15:19:58

en faisant la requête de base mentionnée dans votre question postée, vous ne pourrez pas voir les propriétés de L'utilisateur à moins de retourner un type anonyme comme suit:

from a in Actions
join u in Users on a.UserId equals u.UserId
select new
{
   actionUserId = a.UserId
   .
   .
   .
   userProperty1 = u.UserId
};

Cependant pour utiliser la méthode Include sur L'ObjectContext vous pouvez utiliser ce qui suit:

assurez-vous d'avoir désactivé le téléchargement en utilisant la ligne suivante:

entities.ContextOptions.LazyLoadingEnabled = false;

puis procéder par

var bar = entities.Actions.Include("User");
var foo = (from a in bar
           select a);
2
répondu Ryan 2011-07-21 10:18:29

j'utilise pour cela L'option LoadWith

var dataOptions = new System.Data.Linq.DataLoadOptions();
dataOptions.LoadWith<Action>(ac => as.User);
ctx.LoadOptions = dataOptions;

c'est tout. ctx est votre DataContext. Cela fonctionne pour moi :-)

0
répondu Mariusz 2011-07-20 11:34:47