2010-04-17 1 views
3

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

ответ

6

Я решил изменить мой оригинальный ответ дал свое мышление на этих типах вещей развивалась с начала 2010 года

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

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

+0

Это не очень хороший ответ, потому что он нарушает SRP для Binder. Целью связующего является связывание с запросом. Вы легко можете получить сценарий, когда ваша бизнес-логика истекает кровью в ModelBinder. Тестирование единиц становится более сложным. –

+0

Хотя я не смог сформулировать, почему в 2010 году, я, конечно, согласился бы сегодня. –

+0

Спасибо, что нашли время, чтобы обновить это, и я полностью согласен с вами. –

1

Я бы сказал, нет.

Вот почему: Это создало бы зависимость от вашей базы данных для проверки действий вашего контроллера, что было бы нелегко абстрагироваться.

+0

Как обычно, я даю действию полностью заполненную модель в качестве параметра, полностью пропуская привязку к модели в своих модульных тестах? Почему код, находящийся под контролем, заботится о том, как построена модель? – tvanfosson

+0

Если ваша модель привязана к HttpPost, а некоторые из базы данных, и она либо будет привязана к связующему устройству контроллера/репозитория/модели, то не будет использовать связующее устройство модели, чтобы быть чистым способом избежать дублирования функций, которые могут потребоваться на добавить и изменить операции? – Jimbo

+0

Относительно: «Это создало бы зависимость от вашей базы данных для проверки действий вашего контроллера, что было бы нелегко абстрагироваться». Это неверно. Вы можете легко получить доступ ко всему, что находится внутри вашего контроллера внутри вашего модельного блока, нет никакой дополнительной зависимости, которую вы создаете. Поэтому, если вы вводите DAL/Repository/Service в свой контроллер, вы также можете получить его в своем Modelbinder. – jfar

4

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

2

Я думаю, что это прекрасно, и использовать эту технику все время.

Единственные аргументы против очень педантичны и представляют собой аргументы в пользу философии. IMHO вы можете поместить код «заполнить недостающие опубликованные данные» в ваше приложение MVC как метод в вашем базовом контроллере против метода в вашем ActionFilter против метода в вашем ModelBinder. Все зависит от того, кто получит какую-то ответственность. Для меня модельное связующее может сделать намного больше, чем просто подключить некоторые свойства из опубликованных значений.

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

//logic not in modelbinder 
    public ActionResult Edit(KittyCat cat) 
    { 
     DoSomeOrthagonalDatabaseCall(cat); 

     return View(new MODEL()); 
    } 

против

//logic in model binder 
    public ActionResult Add(KittyCat cat) 
    { 
     return View(new MODEL()); 
    } 
+1

За исключением того, что, когда кто-то приходит с тем, кто знаком с MVC, он теперь получает приятный «счастливый» момент WTF, когда обнаруживает, что модель полностью заполнена данными, даже если она не была отправлена ​​из базы данных и нет указаний откуда он может исходить.Затем он получает возможность копать много несвязанного кода в совершенно другом разделе, чтобы найти «ага» - здесь есть настраиваемое связующее устройство, которое выполняет магию, заполняя недостающие свойства, в том числе ту, которая непреднамеренно осталась в стороне от формы , Извините, но я бы предпочел сделать это очевидным для бедного сока. – tvanfosson

+1

Аргумент «нового парня» довольно беден. Любой, знакомый с asp.net mvc, будет знать, чтобы проверить привязку модели, если параметр метода действия «таинственно» имеет некоторые значения, которые не были отправлены с формой. Ваша критика плоха, если просто спросить другого разработчика. «Эй, откуда берутся эти ценности?» решает всю проблему. Эти аргументы «нового парня», похоже, тщательно строят мир, поскольку опыт или обмен информацией не существует. – jfar

2

Это нарушает способ MVC предполагается работать. ModelBinder предназначен для подбора моделей из данных, поступающих из представления. Пополнение отсутствующей информации из базы данных - это то, что должно быть обработано контроллером. В идеале для этого был бы тот же класс уровня данных/репозитория.

Причина, по которой это должно быть в контроллере, состоит в том, что этот код является бизнес-логикой. Бизнес-правила диктуют, что некоторые данные могут отсутствовать и, следовательно, они должны обрабатываться мозгом операции, контроллером.

Сделайте еще один шаг, скажите, что вы хотите войти в БД, какую информацию пользователь не публикует, или поймать исключение при получении отсутствующих данных и админов по электронной почте об этом. Вы должны поместить их в свое связующее устройство таким образом, и оно становится все более уродливым, когда ModelBinder становится все более искаженным от своей первоначальной цели.

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

+0

Отклоненные аргументы в области связывания, бизнес-логика относится к доменному слою вашего приложения, а не к вашим контроллерам. Вы не хотите, чтобы все, кроме ваших контроллеров, были настолько тупыми, насколько это возможно, на самом деле вам нужна полная противоположность. Контроллеры - это просто точка входа в приложение, которая переводит запрос пользователя в действия, выполняемые на объектах модели домена. Я бы порекомендовал вам ознакомиться с концепциями дизайна, основанными на доменах, а затем принести то, что вы узнали там, в MVC. Я думаю, вы увидите вещи совсем по-другому. –

+0

Что вы подразумеваете под бизнес-логикой? Может быть, я смущен в своем понимании этого. Я не говорю, что контроллер выполняет операции низкого уровня и, следовательно, умный. Я говорю, что контроллер решает, что делать, но не знает, как это делается. Это решение о том, что делать, это то, что я считаю бизнес-логикой. Это глупо в том смысле, что без модели она беспомощна. У вас есть хорошая статья о доменном дизайне? – Alistair

1

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

1 Доступ к базе данных должен быть абстрагирован через интерфейсы репозитория. Интерфейсы репозитория являются частью модели домена, и их реализация является частью уровня доступа к инфраструктуре/данным. Таким образом, нет никакой зависимости от базы данных.

2- Модульные связки и контроллеры являются частью уровня представления, реализованного с использованием ASP.NET MVC Framework. Если контроллерам разрешен доступ к базе данных с использованием интерфейсов репозитория, как не допускаются модели Binders?

Кроме того, есть ситуации, в которых вы бы «лучше» заполнили недостающие данные в вашей модели из Model Binders. Рассмотрим сценарий, в котором у вас есть раскрывающийся список на вашем представлении. При первом загрузке представления выпадающий список заполняется. Пользователь отправляет форму, но проверка не выполняется. Поэтому вам нужно снова вернуть форму. На этом этапе вам нужно будет повторно заполнить список в раскрывающемся списке «Модель». Делать это в контроллер выглядит некрасиво:

public ActionResult Save(DocumentViewModel viewModel) 
{ 
    if (!ModelState.IsValid) 
    { 
     viewModel.Categories = _repository.GetAll(); 
     return View(viewModel); 
    } 
} 

Я считаю, что инициализация Категории здесь некрасиво и как код запах. Что делать, если у вас было несколько свойств, которые необходимо было заполнить из базы данных? Что делать, если у вас было более одного действия с DocumentViewModel в качестве аргумента? Вам придется повторять этот уродливый шаг снова и снова. Лучший подход - заполнить все свойства модели с помощью модуля Binder и передать его контроллеру. Таким образом, объект, который передается контроллеру, находится в «согласованном» состоянии.

Смежные вопросы