ViewModels с asp.net mvc 4 и EntityFramework в чем суть
Я спорю с самим собой, какой смысл создавать классы ViewModel в проекте, который использует Entity Framework?
В настоящее время у меня есть проект, который использует EntityFramework. Мое решение структурировано в основном так:
- Проект пользовательского интерфейса (содержит контроллеры и представления)
- Модельный проект (содержит модель EntityFramework)
- Проект сервисов (содержит классы сервисов, которые общаются с Модельным Проектом для обслуживания объектов из модельного проекта в проект пользовательского интерфейса)
Мои контроллеры передают сущности, которые Entity Framework создает прямо в представление.
Это красиво и просто.
В прошлом я создавал отдельные классы моделей представлений и сопоставлял их с сущностями, которые EntityFramework создает для этих моделей представлений. Но сейчас я изо всех сил пытаюсь понять суть.
В настоящее время я помогаю проекту, который сопоставляет сущности, созданные структурой сущностей, для просмотра моделей. Это фактически использует AutoMapper, чтобы сделать это.
Теперь все это требует больших усилий и кода для очень небольшого выигрыша.
Я что-то здесь упускаю?
3 ответа
Я могу вспомнить пару случаев, когда отдельный уровень классов модели представления является хорошим способом, и я попытаюсь объяснить их в терминах общего инструмента ORM и общей инфраструктуры MVC - обратите внимание, что ни один из этих двух случаи специфичны для ASP.NET MVC Framework с Entity Framework (и даже для программирования на.NET...).
Также: обратите внимание, что в следующих нескольких параграфах я имею в виду только просмотр моделей. В конце этого поста я расскажу о таких проблемах, как уязвимости в массовых назначениях.
Причина 1: Дайте слою View именно те данные, которые ему нужны, и больше ничего
Это несколько "пуристическая" цель - в настоящем приложении MVC уровень представления имеет доступ только к тем данным, которые ему нужны в данный момент, и ничего больше. Объект модели представления теперь становится спецификацией от уровня представления к контроллеру: "Это данные, которые мне нужны для отображения запрошенного вами представления". Чтобы придерживаться фундаментальных принципов MVC, вы должны убедиться, что все решения о том, какие данные отображать, принимаются контроллером.
Другими словами, если вы хотите отобразить имя и фамилию пользователя, имя пользователя и изображение, вам не нужно (или не нужно) предоставлять слою представления объект, который также содержит информацию о пароле пользователя, его ролях (или возьмите некоторые свойства, которые могут быть не такими чувствительными, как высота или отчество). Вместо этого вы даете представлению объект со свойствами для имени, фамилии, имени пользователя и изображения, и представление решает только то, как представить данные. Таким образом, вы уверены, что решение о том, какие данные будут представлены, остается на уровне контроллера.
Причина 2: избегайте проблем с возможностями отслеживания вашего инструмента ORM
Некоторые инструменты ORM- даже те, которые возвращают обычные объекты 1 - используют довольно сложные методы для отслеживания изменений в объектах, которые вы получаете от слоя данных, чтобы упростить изменение записей. Например, вы можете получить объект из хранилища данных, изменить некоторые свойства в этом экземпляре и затем вызвать save()
метод где-то еще, и объект обновляется в базе данных. В зависимости от инструмента ORM, перенаправление ваших ORM-сущностей на уровень представления может иметь любой диапазон последствий, от проблем с производительностью (наихудший случай: соединения с базой данных остаются открытыми) до нежелательных эффектов (скажем, ошибка в слое представления изменяет свойства в хранилище данных). Чтобы избежать этого, переназначьте ваши сущности на "настоящие обычные объекты", которые не имеют никакого отношения к вашему инструменту ORM, прежде чем отправлять их слишком далеко вниз по конвейеру приложения. Просмотр моделей - один из многих способов достижения этой цели.
Обратите внимание, что это необходимо или нет, полностью зависит от вашего инструмента ORM. Я не достаточно хорошо знаю внутреннюю работу Entity Framework, чтобы знать, нужно ли вам о ней заботиться - но в (очень) ранних воплощениях EF это было проблемой, по крайней мере, когда не использовался подход Code-First.
Выводы: вам нужно заботиться?
Нет, не обязательно Без моделей представления вы могли бы нормально работать, и в этом случае это всего лишь еще один уровень абстракции, который на самом деле не добавляет ничего, кроме сложности к вашему приложению. Все сводится к тому, как ваш ORM-инструмент предъявляет какие-либо требования к вашему коду, а также к тому, являетесь ли вы "пуристом MVC".
Примечание: а как насчет уязвимостей массового назначения?
Andrés Nava - .NET уже указала, что уязвимости массового назначения могут быть проблемой. Я согласен, что это серьезная проблема, но я не согласен, что она решается с помощью моделей представления.
Для меня модель представления - это объект передачи данных от контроллера к представлению, помогающий контроллеру отсортировать и обобщить данные, которые должны отображаться. Чтобы избежать таких проблем, как уязвимости массового назначения, я обычно использую модели редактирования, которые очень похожи на модели просмотра, но в другом направлении - то есть на контроллер. Не все делают это различие - и мне все равно, если вы или нет. Но, используя этот словарь, я бы рекомендовал всегда использовать редактирование моделей, когда вы позволяете пользователям изменять ваши данные, и использовать модели просмотра только тогда, когда это вам помогает.
1 В.NET обычно упоминается как "POCO's", или "Обычные старые объекты CLR". Java имеет свою эквивалентность в POJO (Plain Old Java Objects), и если вы можете думать о языке, который можно использовать в объектно-ориентированном программировании, этот язык также имеет эквивалентность.
Мне лично нравится использовать ViewModels, потому что они могут содержать информацию, относящуюся к представлению. Но в основном, как способ предотвратить выставление моих сущностей прямо на вид.
Дополнительным преимуществом является избежание уязвимостей массового назначения. Они также существуют в Ruby.
Я хотел бы взглянуть на этот вопрос Что такое ViewModel в MVC, который объясняет назначение ViewModel.
Нет ничего плохого в том, чтобы передавать Модель непосредственно из вашей сущности в представление, но ViewModel можно использовать, когда ваша модель не соответствует точным данным, которые вам нужны.