Как синтаксис выражения LINQ работает с Include () для быстрой загрузки - PullRequest
31 голосов
/ 20 июля 2011

У меня есть запрос ниже, но я хочу выполнить функцию Include () для загрузки свойств загрузки. Действия имеют свойство навигации, Пользователь (Action.User)

1) Мой основной запрос:

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

2) Первая попытка:

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

Но Action.User заполнен , а не заполнен.

3) Попробуйте загрузить «User» в свойство навигации в действии вне запроса:

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

В LINQPad при попытке включить я получаю сообщение об ошибке:

'System.Linq.IQueryable' не содержит определения для 'Включить' и нет метода расширения 'Включить', принимающего первый аргумент типа 'System.Linq.IQueryable' (нажмите F4 для добавления директивы using или ссылка на сборку)

Я думаю, это потому, что LINQ не поддерживает Include ().

Итак, я попробовал в VS; запрос 2 выполняется, но возвращает незаселенное свойство пользователя. В запросе 3 метод расширения, по-видимому, не существует, хотя он существует в самом Action без запроса.

Ответы [ 5 ]

59 голосов
/ 21 июля 2011

Я понял, спасибо за предложения в любом случае.Решение состоит в том, чтобы сделать это (2-я попытка в моем вопросе):

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

Причина, по которой intellisense не показывал Включить после запроса, была, потому что мне потребовалось следующее использование:

using System.Data.Entity;

Все работало нормально, делая это.

16 голосов
/ 20 июля 2011

Если вам нужен запрос, который вернет все Action сущности, чья связанная сущность User действительно существует через свойство внешнего ключа Action.UserId , это сделает это:

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

Однако вам не нужно использовать свойства внешнего ключа для фильтрации , поскольку у вас также есть свойства навигации .Таким образом, ваш запрос может быть упрощен путем фильтрации вместо свойства навигации Action.User, как в этом примере:

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

Если ваша модель утверждает, что свойство Action.User никогда не может быть нулевым (то есть Action.UserId внешний ключ не может обнуляться в базе данных), а на самом деле вам нужны все Action сущностей со связанными с ними Users, тогда запрос становится еще проще

var results = context.Actions.Include("User");
14 голосов
/ 14 февраля 2017

Лучший, дружественный к рефакторингу код (EF6)

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

или

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

Обновление 3/31/2017

Вы также можете использовать включение в лямбда-синтаксис для любого метода:

var x = from cart in context.ShoppingCarts.Include(p => p.ShoppingCart.CartItems))
        where table.id == 123
        select cart;
2 голосов
/ 21 июля 2011

При выполнении основного запроса, упомянутого в опубликованном вопросе, вы не сможете увидеть свойства пользователя, если не вернете анонимный тип следующим образом:

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

Однако для использования метода Include в ObjectContextВы можете использовать следующее:

Убедитесь, что LazyLoading отключен, используя следующую строку:

entities.ContextOptions.LazyLoadingEnabled = false;

Затем выполните

var bar = entities.Actions.Include("User");
var foo = (from a in bar
           select a);
0 голосов
/ 20 июля 2011

Я использую для этого опцию LoadWith

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

Вот так. ctx - это ваш DataContext.Это работает для меня: -)

...