#entity-framework #asp.net-mvc-2 #repository-pattern
#entity-framework #asp.net-mvc-2 #репозиторий-шаблон
Вопрос:
Я пытаюсь заставить шаблон репозитория работать с MVC2 и EF. Моя проблема заключается в конкретном репозитории. Когда я пытаюсь преобразовать результаты запроса EF в виде нечисляемой коллекции объектов модели представления:
Unable to cast object of type
'System.Data.Objects.ObjectQuery`1[Data_Service.MediaReleases]'
to type
'System.Collections.Generic.IEnumerable`1[TestMVCWithFacory.Models.Entities.MediaReleaseModel]'.
Я чувствую, что пытаться сделать это глупо — и это что-то с Linq, и как работает отложенное выполнение, но я действительно не понимаю вуду.
Так что же я там неправильно понимаю и как мне это исправить?
Модель представления:
public class MediaReleaseModel
{
public string Headline { get; set; }
public string FullText { get; set; }
}
Интерфейс репозитория:
public interface IMediaReleasesRepository
{
IEnumerable<MediaReleaseModel> MediaReleases { get;}
}
Конкретный репозиторий:
public class MediaReleaseRepository : IMediaReleasesRepository
{
private NewsEntities DataContext = new NewsEntities();
private IEnumerable<MediaReleases> _MRs;
public MediaReleaseRepository()
{
_MRs = from art in DataContext.MediaReleases select art;
}
public IEnumerable<MediaReleaseModel> MediaReleases
{
get { return (IEnumerable<MediaReleaseModel>)_MRs; }
}
}
Контроллер:
public class HomeController : Controller
{
private IMediaReleasesRepository _MRRepository;
public HomeController()
{
_MRRepository= new MediaReleaseRepository();
}
public ViewResult index()
{
return View(_MRRepository.MediaReleases.ToList());
}
}
Ответ №1:
Вы пытаетесь преобразовать коллекцию MediaRelease
объектов в коллекцию MediaReleaseModel
объектов. Если MediaReleaseModel
это отдельный класс, это не может быть сделано просто путем приведения. Как правило, приведение будет успешным только в одной цепочке наследования или когда определены операторы преобразования, чего здесь нет.
Что вам здесь нужно, так это переписать MediaRelease
поля для вашего объекта модели (это может быть автоматизировано с помощью таких инструментов, как AutoMapper), т. е. с помощью LINQ:
public IEnumerable<MediaReleaseModel> MediaReleases
{
get
{
return _MRs.Select(x => new MediaReleaseModel()
{
Prop1 = x.Prop1
/* etc. */
});
}
}
Одно предложение сбоку: лучше не использовать подобную логику в конструкторе, создание объектов должно быть дешевой операцией, и немного странно, когда данные извлекаются до того, как они действительно понадобятся.
Комментарии:
1. Спасибо. Re: ваша последняя строка: вы ссылаетесь на инструкцию linq в MediaReleaseRepository, правильно? (не вызывается репозиторий в конструкторе контроллера?)
2. ДА. Как правило, конструкторы должны только собирать зависимости и избегать выполнения «реальной работы». Ваш запрос может быть легко перемещен в
MediaReleases
свойство.