Должно ли приложение ASP.NET MVC напрямую использовать Entity Framework в качестве модели?

22

Я создаю свое первое приложение MVC в Visual Studio 2013 (MVC 5), и мне немного неясно, как лучше настроить мою модель.

Я сгенерировал модель структуры сущности, используя код сначала из существующей базы данных. Моим первым инстинктом было создание некоторых промежуточных классов, которые были бы моделью, используемой представлениями, и чтобы эти классы работали с классами структуры сущностей.

Когда я писал промежуточные классы, я осознал, что я в основном просто перевоплощал многое из того, что классы EF уже делали с помощью случайного частного установщика или приведения из одного типа данных в другой. Так что это казалось пустой тратой.

Является ли общим правилом прямое использование классов структуры сущностей в качестве модели для приложения MVC? Или есть какая-то выгода, которую мне не хватает для создания этих промежуточных классов?

Майк Д.
источник
1
Это может помочь: programmers.stackexchange.com/questions/123011/…
oasten
Если вы использовали сначала код, то базы данных не было, нет?
Исаак Кляйнман
1
С EF 6.1+ вы можете сгенерировать первую модель кода из существующей базы данных. См. Эту статью MSDN: msdn.microsoft.com/en-au/data/jj200620.aspx
Майк Д.

Ответы:

23

В моих приложениях я всегда разделял вещи, используя разные модели для базы данных (Entity Framework) и MVC. Я также разделил их на разные проекты:

  • Example.Entities - содержит мои сущности для EF и контекст БД для доступа к ним.
  • Example.Models - содержит модели MVC.
  • Example.Web - веб-приложение. Зависит от обоих Example.Domain и Example.Models.

Вместо хранения ссылок на другие объекты, как это делают сущности домена, модели MVC содержат идентификаторы как целые числа.

Когда поступает запрос GET для страницы, контроллер MVC выполняет запрос к базе данных, который возвращает объект. Я написал методы "Converter", которые берут предметную сущность и преобразуют ее в модель MVC. Существуют и другие методы, которые делают обратное (от модели MVC до сущности домена). Затем модель передается в представление и, следовательно, клиенту.

Когда приходит запрос POST, контроллер MVC получает модель MVC. Метод конвертера преобразует это в объектную сущность. Этот метод также выполняет любые проверки, которые не могут быть выражены как атрибуты, и гарантирует, что, если сущность домена уже существует, мы обновляем ее, а не получаем новую. Методы обычно выглядят примерно так:

public class PersonConverter
{
    public MyDatabaseContext _db;

    public PersonEntity Convert(PersonModel source)
    {
         PersonEntity destination = _db.People.Find(source.ID);

         if(destination == null)
             destination = new PersonEntity();

         destination.Name = source.Name;
         destination.Organisation = _db.Organisations.Find(source.OrganisationID);
         //etc

         return destination;
    }

    public PersonModel Convert(PersonEntity source)
    {
         PersonModel destination = new PersonModel()
         {
             Name = source.Name,
             OrganisationID = source.Organisation.ID,
             //etc
         };

         return destination;
    }
}

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

Выполнение этих действий дает множество преимуществ:

  • Вы можете настроить модель для конкретного вида или действия. Скажем, у вас есть форма регистрации для человека, которая при отправке создает много разных объектов (человек, организация, адрес). Без отдельных моделей MVC это будет очень сложно.
  • Если мне нужно передать в представление больше информации, чем было бы доступно в сущности, или объединить две сущности в одну модель, то мои драгоценные модели баз данных никогда не будут затронуты.
  • Если вы когда-либо сериализуете модель MVC как JSON или XML, вы получаете сериализованную только непосредственную модель, а не любую другую сущность, связанную с этой.
Джек скотт
источник
Хороший ответ, рекомендовал бы использовать ValueInjector или что-то подобное (лично я ненавидел автопереключатель) вместо того, чтобы вручную отображать свойства из одного класса в другой.
Rocklan
1
Вместо того, чтобы добавлять отдельный ответ, я просто прокомментирую здесь, что в практике DDD ваши «конвертеры» и отдельные модели для представления будут считаться частью уровня обслуживания приложений. По сути, это позволяет вашей доменной модели быть настолько сложной, насколько это необходимо, скрывая эту сложность от приложения. Это также защищает приложение от необходимости изменения из-за изменения модели предметной области. ASL обрабатывает перевод.
Майкл Браун
Таким образом, вы вызываете каждую модель, имеющуюся в вашей PersonModel (т.е. объект Organization), чтобы получить информацию об этой модели? Скажем, у вас есть форма для обновления информации о человеке и организации, будет ли у вас дополнительный звонок при обновлении Организации? Я использую хранимые процедуры, поэтому я не могу отправить все атрибуты модели и любые содержащие атрибуты модели одновременно?
Световой
1
Как бы вы справились с сопоставлением коллекции? Кажется, в EF6 все было намного сложнее, поскольку вы больше не можете просто создавать новый список сущностей с обновлениями, поскольку это просто воссоздает все ...
Джерард Уилкинсон
2
Вместо того, чтобы писать собственные классы конвертера, я бы порекомендовал использовать библиотеку Automapper, которая была написана для решения этой проблемы. Он сильно повзрослел с 2014 года!
BenSmith
6

Я бы сказал, что это действительно зависит от вашего приложения. Это просто делает чистый CRUD, без какой-либо бизнес-логики? Тогда я бы использовал модели EF прямо в моих взглядах.

В большинстве случаев, по крайней мере, присутствует некоторая бизнес-логика, и тогда хорошей идеей может быть слой между моделями данных / EF и представлением. В этом случае может быть целесообразно выполнить «CQRS-lite» (см. Ниже) и использовать разные модели для и из вашего контроллера. Чаще всего читаемые модели намного "толще", чем пишущие модели ...

Однако, если приложение содержит много бизнес-логики и / или нуждается в большом масштабировании, я бы реализовал по крайней мере ее ядро, используя CQRS (сегрегация ответственности при выполнении командных запросов), DDD (управляемый доменом дизайн) и, возможно, источник событий. Тогда EF может быть использован в качестве читаемого фасада модели.

Также помните, что вам не нужно придерживаться одной стратегии / шаблона для всего приложения, некоторые области могут быть просто CRUD, а другие могут содержать много бизнес-логики ...

jhdrn
источник