Взгляните на S # arp Architeture . Это как лучшая архитектура для построения приложений ASP.NET MVC. Общий шаблон архитектуры должен иметь 1 хранилище на объект, который отвечает только за доступ к данным, и 1 службу на хранилище, которое отвечает только за бизнес-логику и связь между контроллерами и службами.
Чтобы ответить на ваши вопросы на основе S # arp Architeture:
В дополнение к уровню обслуживания, должен ли также быть отдельный уровень бизнес-логики или это роль уровня обслуживания?
Модели должны отвечать за проверку на уровне поля (например, используя обязательные атрибуты поля), в то время как контроллеры могут проверять данные перед сохранением (например, проверка состояния перед сохранением).
Должен ли быть один уровень обслуживания для каждого хранилища?
Да - должен быть один сервис на репозиторий (не 1 сервисный уровень на репозиторий, но я предполагаю, что вы это имели в виду).
Является ли уровень службы единственным способом, с помощью которого пользовательский интерфейс может создавать экземпляры объектов модели, или репозиторий предоставляет новый экземпляр модели службе?
Хранилища и службы могут возвращать одну сущность, коллекцию сущностей или объекты передачи данных (DTO) по мере необходимости. Контроллеры передадут эти значения статическому методу конструктора в модели, который возвратит экземпляр модели.
ex Использование DTO:
GiftCertificateModel.CreateGiftCertificate(int GiftCerticiateId, string Code, decimal Amount, DateTime ExpirationDate)
Помещаю ли я свой параметр, модель и другие проверки в сервисный уровень, который выполняет такие вещи, как проверка, чтобы убедиться, что вход действителен и что элемент для обновления существует в базе данных перед обновлением?
Модели проверяют значения на уровне поля, напр. убедиться, что ввод действителен, проверив обязательные поля, возраст или диапазон дат и т. д. Службы должны выполнить любую необходимую проверку, которая требует проверки вне значения модели, например. Проверка того, что подарочный сертификат еще не был погашен, проверка свойств магазина, для которого предназначен подарочный сертификат).
Могут ли модель, хранилище и пользовательский интерфейс выполнять вызовы на уровне обслуживания, или это только для пользовательского интерфейса?
Контроллеры и другие службы должны быть единственными, выполняющими вызовы на уровне служб. Сервисы должны быть единственными, которые делают звонки в репозитории.
Предполагается ли, что на уровне сервиса все статические методы?
Они могут быть, но их легче поддерживать и расширять, если это не так. Изменения в сущностях и добавление / удаление подклассов легче изменить, если на сущность / подкласс имеется 1 услуга.
Каков типичный способ вызова уровня обслуживания из пользовательского интерфейса?
Некоторые примеры контроллеров, вызывающих сервисный уровень:
giftCertificateService.GetEntity(giftCertificateId); (which in turn is just a call to the giftCertificateRepository.GetEntity(giftCertificateId)
giftCertificateService.Redeem(giftCertificate);
Какие проверки должны быть на модели по сравнению с уровнем обслуживания?
Уже ответили выше.
UPDATE
Поскольку вы используете WebForms, может быть немного сложнее понять некоторые концепции, но все, что я упомянул, применимо, поскольку то, что я описываю, является общей парадигмой MVC. ADO.NET для доступа к данным не имеет значения, поскольку доступ к данным отделен через репозитории.
Добавляю ли я к сервису те же (и, возможно, больше) свойства, что и для моей модели (количество, код и т. Д.), Или я предлагаю только методы, которые принимают объекты GiftCertificate и прямые параметры?
Вы должны смотреть на сервисы как на то, что подразумевает их имя - действия, которые могут вызывать контроллеры. Вам не понадобятся свойства, определенные в вашей модели, поскольку они уже доступны в модели.
Создаю ли я экземпляр по умолчанию сущности GiftCertificate при вызове конструктора Service или просто создаю новые по мере необходимости (например, - для методов проверки в службе, которые должны вызывать методы проверки в сущности? Кроме того, тот же вопрос о создании экземпляра репозитория по умолчанию ...?
Контроллеры и службы должны иметь закрытые поля для служб и хранилищ соответственно. Вам не следует создавать экземпляры для каждого действия / метода.
Я знаю, что я раскрываю функциональность репо через сервис, я также выставляю методы из сущности (например, - IsValidCode и т. Д.)?
Не совсем уверен, что вы имеете в виду здесь. Если сервисы возвращают сущности, то эти методы для сущностей уже доступны. Если они возвращают DTO, это означает, что вы заинтересованы только в определенной информации.
Для проверки я понимаю, почему вас это немного беспокоит, поскольку проверка выполняется непосредственно на модели, а другие типы проверки выполняются в сервисах. Эмпирическое правило, которое я использовал, заключается в том, что если проверка требует обращения к БД, то это должно быть сделано на уровне службы.
Пользовательский интерфейс может просто создать новый объект GiftCertificate напрямую, без прохождения через службу (например, для вызова методов проверки параметров из сущности). Если нет, то как это обеспечить?
На уровне пользовательского интерфейса, когда я хочу создать новый подарочный сертификат, я вызываю проверки модели / сервиса (например, IsValidExpirationDate и т. Д.) Непосредственно из уровня пользовательского интерфейса ИЛИ сначала гидратирую объект, а затем передаю чтобы его можно было проверить, а затем вернуть какой-либо сводный результат проверки обратно в пользовательский интерфейс?
Для этих 2 вопросов давайте рассмотрим сценарий:
Пользователь вводит информацию для создания нового сертификата и отправляет. Существует проверка на уровне поля, поэтому, если текстовое поле имеет нулевое значение или сумма в долларах отрицательна, возникает ошибка проверки. Предполагая, что все поля действительны, контроллер вызовет службу gcService.Save(gc)
.
Служба проверит другую бизнес-логику, например, если магазин уже выпустил слишком много подарочных сертификатов. Он либо возвращает перечисление для статуса, если имеется несколько кодов ошибок, либо выдает исключение с информацией об ошибке.
Наконец, служба звонит gcRepository.Save(gc)
.