Фон
ArticleService
- это класс, предоставляющий методы для интерфейсных слоев для облегчения работы с серверной частью.
Двумя основными обязанностями является преобразование ViewModels (ArticleViewModel
) в соответствующие модели (Article
) при сохранении данных, и наоборот - преобразование моделей в ViewModels при извлечении данных ... так часто, что я создавал частный метод построения объектов ViewModel:
private ArticleViewModel BuildViewModel(Article a)
{
return new ArticleViewModel { Title = a.Title /* all properties */ }
}
Продвигаясь вперед, ArticleService
предоставляет метод для извлечения всех статей из хранилища данных, возвращая их как ViewModels: public IEnumerable<ArticleViewModel> All()
Класс вызова использует его так: var articleViewModels = _articleService.All();
Простой, верно?
Проблема:
Я изначально писал All()
лениво с классическим циклом foreach
:
private IEnumerable<ArticleViewModel> All()
{
var viewModels = new List<ArticleViewModel>();
foreach (var article in _db.Articles)
viewModels.Add(BuildViewModel(article));
return viewModels;
}
Работало нормально - articleViewModels
был список всех моделей представлений.
Затем я использовал ReSharper для преобразования этого цикла в оператор LINQ для повышения производительности и красивости, а затем объединил оператор присваивания с оператором возврата. Результат:
private IEnumerable<ArticleViewModel> All()
{
return _db.Articles.Select(article => BuildViewModel(article)).ToList();
}
Я отладил оператор LINQ, и зверь проснулся:
LINQ to Entities не распознает метод ArticleViewModel
BuildViewModel (Article) ', и этот метод не может быть преобразован в выражение хранилища.
Вопрос. Почему этот оператор LINQ нарушает мой код?
Примечание. Возвращение к явному объявлению, присваиванию, возврату сработало с оператором LINQ, поэтому я почти уверен, что это как-то связано с лямбда-логикой.