Чи повинен програма 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 виконує запит бази даних, який повертає сутність. Я написав методи "Конвертер", які беруть об'єкт домену і перетворюють його в модель 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 (тобто об'єкт організації), щоб отримати інформацію про цю модель? Скажімо, у вас є форма для оновлення інформації про особу та інформацію про організацію, чи буде у вас додатковий дзвінок під час оновлення Організації? Я використовую збережені програми, тому не можу я надсилати відразу всі атрибути моделі та будь-які атрибути, що містять модель?
Світлий

1
Як би ви попрацювали зі складанням колекції назад? Це, здається, було набагато складніше в EF6, оскільки ви більше не можете просто створити новий список об'єктів з оновленнями, оскільки це просто відновлює все ...
Джерард Вілкінсон

2
Замість того, щоб писати власні класи перетворювачів, я б рекомендував використовувати бібліотеку Automapper, написану для вирішення цієї проблеми. Він дуже дозрів з 2014 року!
BenSmith

6

Я б сказав, що це дійсно залежить від вашої заявки. Це просто чистий CRUD, без ділової логіки? Тоді я б використовував моделі EF безпосередньо в своїх поглядах.

Більшу частину часу займається хоча б деяка бізнес-логіка, і тоді шар між моделями даних / EF та переглядом може бути хорошою ідеєю. У цьому випадку може бути доречним зробити "CQRS-lite" (див. Нижче) та використовувати різні моделі для вводу та виходу з вашого контролера. В більшості випадків моделі, що читаються, значно "товстіші", ніж моделі запису ...

Однак якщо додаток містить велику ділову логіку та / або потребує масштабного масштабування, я би реалізував принаймні його основу за допомогою CQRS (розділення відповідальності за запити команд), DDD (дизайн, керований доменом) та, можливо, пошук подій. Тоді EF можна використовувати як фасад зчитуваної моделі.

Також пам’ятайте, що вам не потрібно дотримуватися однієї стратегії / структури для всього додатка, деякі області можуть бути чистими CRUD, а інші області можуть містити багато ділової логіки ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.