Проблема с активной загрузкой вложенной навигации на основе абстрактного объекта (EF CTP5) - PullRequest
5 голосов
/ 04 марта 2011

Я часть моей модели EF, которая выглядит следующим образом:

enter image description here

Описание:

  • Местоположение имеет много сообщений
  • Пост аннотация класс
  • Обсуждение Происходит от Сообщение
  • В обсуждениях много комментариев

Теперь запрос, который я пытаюсь выполнить:

Получение информации о Location Id 1234, включая любые обсуждения и комментарии, связанные с этими обсуждениями.

Я могу получить обсуждения и комментарии вроде этого:

var discussions = ctx.Posts
                     .OfType<Discussion>()
                     .Include(x => x.Comments)
                     .ToList();

Но я не могу получить его, основываясь на навигации Posts на Location entity.

Я пробовал это:

var locationWithDiscussionsAndComments = ctx
                    .Locations
                    .Include(x => x.Posts
                                   .OfType<Discussion>()
                                   .Select(y => y.Comments))
                    .SingleOrDefault();

Что компилируется, но я получаю ошибку:

System.ArgumentException: выражение включения пути должно ссылаться на свойство, определенное сущностью, при необходимости также с вложенными свойствами или вызовами Select. Имя параметра: путь

Есть идеи? Я мог бы, вероятно, пойти "назад" из сообщений:

var locationWithDiscussionsAndComments = ctx
                   .Posts
                   .Include(x => x.Location)
                   .OfType<Discussion>()
                   .Include(x => x.Comments)
                   .Where(x => x.LocationId == 1234)
                   .Select(x => x.Location)
                   .ToList();

Но это и волосато, и семантически неправильно с точки зрения моих репозиториев (мне не нужно было проходить через репозиторий постов, чтобы получить информацию о местоположении).

Есть идеи?

EDIT

Поэтому, подумав об этом, я понял, что OfType<T> - это операция фильтра. Как мы знаем, EF не поддерживает фильтрацию с активной загрузкой. Единственные опции - получить все или использовать проекцию анонимного типа.

Никоим образом я не могу получить все, так как в нем слишком много метаданных. Поэтому я пытаюсь проецировать анонимный тип.

1 Ответ

6 голосов
/ 04 марта 2011

Новый метод Query может помочь вам:

var location = context.Locations.SingleOrDefault();

context.Entry(location)
       .Collection(l => l.Posts)
       .Query()
       .OfType<Discussion>()
       .Load();


Реализация репозитория:

Мы можем добавить новый LoadProperty универсальный метод к классу Repository<T>, который использует этот новый QUery метод:

public void LoadProperty<TElement>(T entity, 
        Expression<Func<T, ICollection<TElement>>> navigationProperty,
        Expression<Func<TElement, bool>> predicate) where TElement : class
{
    _context.Set<T>().Attach(entity);

    _context.Entry(entity)         
            .Collection(navigationProperty)
            .Query()
            .Where(predicate)
            .Load();
}

Использование метода LoadProperty:

Location location = _locationRepository.Find(1);
_locationRepository.LoadProperty(location, l => l.Posts, p => p is Discussion);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...