MVC2, Entity Framework и шаблон репозитория

#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 свойство.