Как синтаксис выражения LINQ работает с Include() для активной загрузки
У меня есть запрос ниже, но я хочу выполнить свойство Include() для активных свойств загрузки. Действия имеют свойство навигации, User (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) Попробуйте загрузить "Пользователь" в свойство навигации в действии вне запроса:
(from a in Actions
join u in Users on a.UserId equals u.UserId
select a).Include("User")
В попытке LINQPad включить я получаю сообщение об ошибке:
'System.Linq.IQueryable' не содержит определения для "Include", и не может быть найден метод расширения "Include", принимающий первый аргумент типа "System.Linq.IQueryable" (нажмите F4, чтобы добавить директиву using или ссылку на сборку)
Я думаю, это связано с тем, что LINQ не поддерживает Include().
Итак, я пробовал в VS; запрос 2 работает, но возвращает непопущенное свойство пользователя.
В запросе 3 метод расширения, похоже, не существует, хотя он существует и сам по себе без запроса.
Ответы
Ответ 1
Я понял это, спасибо за предложения в любом случае.
Решение должно сделать это (вторая попытка в моем вопросе):
var qry = (from a in Actions
join u in Users on a.UserId equals u.UserId
select a).Include("User")
Причина, по которой intellisense не показывала Include после запроса, потому что мне понадобилось следующее:
using System.Data.Entity;
Все отлично работало.
Ответ 2
Если вам нужен запрос, который будет возвращать все 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
не имеет значения NULL в базе данных), и на самом деле вы хотите, чтобы все Action
сущности с их ассоциированными Users
то запрос становится еще проще
var results = context.Actions.Include("User");
Ответ 3
Лучший, удобный для рефакторинга код (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;
Обновление 31.03.2017
Вы также можете использовать include в лямбда-синтаксисе для любого метода:
var x = from cart in context.ShoppingCarts.Include(p => p.ShoppingCart.CartItems))
where table.id == 123
select cart;
Ответ 4
Выполняя основной запрос, упомянутый в вашем вопроснике, вы не сможете увидеть свойства пользователя, если вы не вернете анонимный тип следующим образом:
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);
Ответ 5
Я использую для этого параметр LoadWith
var dataOptions = new System.Data.Linq.DataLoadOptions();
dataOptions.LoadWith<Action>(ac => as.User);
ctx.LoadOptions = dataOptions;
Вот оно. ctx - ваш DataContext. Это работает для меня: -)