Подтвердить что ты не робот

ASP.NET MVC - Объекты базы данных или ViewModels?

В настоящее время я работаю над проектом ASP.NET MVC.

Некоторые разработчики в команде хотят связать автоматически сгенерированные объекты базы данных непосредственно с представлениями.

Другие разработчики хотят создать индивидуальный ViewModel и привязать их к представлениям.

Объективно, каковы плюсы и минусы обоих подходов?

(Под "объектами базы данных" я имею в виду автоматически сгенерированные классы, которые генерируют инфраструктура ORM, такие как LINQ to SQL, Entity Framework или LLBLGen).

4b9b3361

Ответ 1

Определенно использовать модели просмотра в своих представлениях и использовать что-то вроде AutoMapper для создания моделей взглядов из объектов легко.

Минусы:

  • Иногда кажется, что вы дублируете код, в частности, когда модель представления и объект имеют те же самые свойства.

Плюсы:

  • Вам часто нужно представлять объект в более простом формате (часто называемом уплощением), но вам нужна полная верность на стороне сервера. Это позволяет вам переходить между ними без смещения вашей модели домена с презентацией cruft.
  • Совокупные корни часто имеют множество объектов значений и дополнительных объектов, которые не имеют отношения к определенному виду, и опускание их в модели представления облегчает работу с.
  • У ваших сущностей будет много двухсторонних ссылок, которые являются разумными с точки зрения API, но создают чистый ад, когда их сериализуют для JSON, XML и т.д. Модели просмотра устраняют эти циклические ссылки.
  • Вы можете часто использовать один и тот же объект, но разными способами для разных видов. Попытка сбалансировать обе потребности на одном типе может создать огромный беспорядок.

Ответ 2

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

  • ORM ленивая загрузка. Представьте, что у вашего клиента есть ленивые заказы коллекции. Вы передаете Клиенту в Вид, и он выполняет итерации над ордерами. Вы выбираете N * 1 в таблице Orders. Но это также означает, что ваше соединение с базой данных должно оставаться открытым в представлении. Существует шаблон, в котором люди используют "транзакцию за действие", которая предоставляет контекст базы данных в событии Action_Executed, которое происходит до отображения вашего представления. Таким образом, вы можете попытаться получить доступ к базе данных после ее удаления. Даже если вы этого не делаете сейчас, кто-то в будущем может решить реализовать этот шаблон, потому что он моден.

  • Проблемы ViewModel отличаются от модели db.. Например, вы обычно украшаете свойства ViewModel атрибутами проверки. Они обычно различаются или касаются только пользовательского интерфейса, а не db. Если вы привяжетесь к своим сущностям базы данных, вы обнаружите, что все эти проблемы пользовательского интерфейса загрязняют вас сущностями DB.

  • В отношении 2 - требования ViewModel могут потребовать вычисленные или производные свойства. Например, полное имя, построенное из имен First и Last. Такие вещи лучше всего хранить в ViewModel.

  • Вы можете выборочно тестировать свои ViewModels отдельно от базы данных. ViewModels может закончиться тем, что содержит довольно много логики, которая должна быть проверена с помощью модуля. Это проще проверить, если он не привязан к вашей базе данных (как и к объектам EF).

В целом, создание и поддержка ViewModels (даже без AutoMapper) не является накладными расходами, и вы обнаружите, что это намного лучший образец развития в целом. Я бы рекомендовал его для всего, кроме самых простых случаев (например, списки поиска статических данных).

Ответ 3

Я считаю, что использование моделей просмотра - единственный способ пойти, поэтому нет плюсов для объектов ORM:). Модели просмотра не только предоставляют данные для просмотра, но также определяют, как должен выглядеть взгляд (путем определения шаблонов) или как он должен проверять (путем добавления аннотаций или реализации IDataErrorInfo).

Использование моделей просмотра:

Плюсы:

  • Просмотр моделей содержит только свойства, необходимые для просмотра, ничего больше.
  • Просмотр моделей может содержать специальные правила проверки с использованием аннотаций данных или IDataErrorInfo.
  • Просмотр моделей может объединять значения из разных объектов базы данных.
  • Просмотр моделей самостоятельно документирует и не привязан к какой-либо инфраструктуре.
  • Просмотр моделей защищает вас от поддельных POST, содержащих значения, которые не были представлены в форме, но содержались в объектах ORM.
  • Вы можете легко указать шаблоны отображения для моделей просмотра и повторно использовать их во многих местах с помощью DisplayFor или EditorFor помощников.

Использование объектов ORM:

Минусы:

  • Объекты ORM уже содержат аннотации данных, которые могут испортить вашу проверку. Пример. Поле пароля у пользователя может быть как Required, но оно не требуется при изменении только базовой информации пользователя.
  • Объекты ORM сильно привязаны к Framework (Entity Framework) и могут быть непростыми в реализации правил.
  • Объекты ORM могут содержать свойства для нескольких видов, но трудно отделить правила проверки для разных представлений.
  • Использование ORM-объектов с ленивой загрузкой может привести к выполнению SQL-запросов при визуализации представлений. Этого не должно быть.
  • Использование ORM-объектов может привести к использованию огромных SQL-запросов вместо небольших. Если вы хотите отображать раскрывающееся меню с именем и фамилией, вы должны получать только имя и фамилию из базы данных, а не целые объекты.

Ответ 4

Спасибо за ответы до сих пор - они оказали большую помощь в понимании плюсов и минусов обоих подходов. У меня есть одна вещь, чтобы добавить, что никто не упомянул.

Атака над публикацией

Недостаток, связанный с привязкой непосредственно к объектам БД, - это "чрезмерная атака". Здесь злоумышленник, используя инструмент, не более продвинутый, чем FireBug, может вставлять поля форм, которые не предназначены для редактирования пользователем, но которые существуют в сущности DB.

Рассмотрим страницу "Редактировать мой профиль". Ваше мнение может выглядеть так:

@using(Html.BeginForm() {
  <div>
    @Html.LabelFor(x=> x.FirstName)
    @Html.TextBoxFor(x=> x.FirstName)
  </div>
  <div>
    @Html.LabelFor(x=> x.LastName)
    @Html.TextBoxFor(x=> x.LastName)
  </div>

  <input type="Submit" value="Save" />
}

Он отобразит следующий HTML-код:

<form action="/profile/edit" method="post">
  <div>
    <label for="FirstName">FirstName</label>
    <input type="text" name="FirstName" value="" />
  </div>
  <div>
    <label for="LastName">LastName</label>
    <input type="text" name="LastName" value="" />
  </div>

  <input type="Submit" value="Save" />
</form>

Используя FireBug, злоумышленнику просто нужно вставить фрагмент HTML внутри формы:

  <input type="hidden" name="IsAdmin" value="true" />

... и внезапно пользователи могут изменять данные очень неожиданно и вредно.

Вот некоторые еще более страшные скрытые поля формы:

  <input type="hidden" name="ShoppingCart.Items[0].Price" value="0.01" />
  <input type="hidden" name="BankAccount.Balance" value="1000000" />
  <input type="hidden" name="User.Administrator.Password" value="hackedPassword" />

Ой!

Информация взята из: http://hendryluk.wordpress.com/tag/asp-net-mvc/

Ответ 5

Однажды я попытался разработать приложение, которое использует объекты NHibernate непосредственно в представлениях ASP.NET. Я столкнулся с множеством проблем с Lazy загрузкой и отложенным выполнением SQL, выполняемым непосредственно из представлений, а не на уровне бизнес-логики или даже контроллеров. Перемещение в режим просмотра и использование automapper, казалось, решить все эти проблемы и сделать приложение легче тестировать, отлаживать и поддерживать.

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

В частности, модели просмотра упростили выбор, если вы хотите выбрать связанные объекты из выпадающих списков.

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

Ответ 6

Не выставляйте бэкэнд-сущности клиенту. Приложение реального мира имеет поведение - не CRUD. Это вы привязываете свои сущности к виду, это будет всего лишь вопросом времени, прежде чем вы начнете копаться в грязном хаке, когда на клиентах требуется поведение.

Ответ 7

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

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

Цель ViewModel заключается в основном в разделении проблем - развязывании представления из деталей реализации модели.

Ответ 8

Использование сущностей DB в ваших представлениях, особенно ваши формы, представляет собой серьезную проблему безопасности. Возьмите следующий объект POCO

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    public string Email { get; set; }
    public bool IsAdmin { get; set; }
}

Теперь скажите, что вы представляете представление, которое позволяет пользователю изменять свой адрес электронной почты. Метод MVC для обработки результата формы при использовании объектов Db вместо моделей просмотра будет выглядеть так: (если вы не используете привязку к модели, в этом случае вы делаете больше работы для себя)

public class HomeController : Controller
{
    [HttpPost]
    public ActionResult ChangeEmail(User user)
    {
        //....
    }
}

Связывание модели в Asp.net работает, ища параметры GET или POST, соответствующие именам свойств в модели. Поэтому все, что нужно сделать пользователю, это добавить IsAdmin=true в параметры POSt и альт, модель, переданная в функцию ChangeEmail, будет иметь свойство IsAdmin, равное true, которое может быть легко случайно добавлено в базу данных, пользователям бесплатный доступ к изменениям данных, к которым у них не было доступа к изменениям.

Это относится к разрешениям пользователей, изменяющим, кто владеет сущностью (связать ваш вопрос со мной, а не с вами), изменить даты создания и т.д.