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

Модели EF и модели обслуживания против моделей (MVC)

Я пытаюсь понять и нарисовать примеры для разработки моделей приложений/доменов (POCOs/DTOs).

Скажем, у меня есть следующая таблица базы данных, Учетная запись:

UserID int
Email varchar(50)
PasswordHash varchar(250)
PasswordSalt varchar(250)

Конечно, EF4 построил бы сущность так:

public class Account
{
    public int UserID { get; set; }
    public string Email { get; set; }
    public string PasswordHash { get; set; }
    public string PasswordSalt { get; set; }
}

Теперь скажем, у меня есть модель просмотра для регистрации нового пользователя, которая может выглядеть примерно так:

public class RegistrationViewModel
{
    public string Email { get; set; }
    public string Password { get; set; }
}

Наконец, у меня есть служба, которая должна регистрировать пользователя:

public class RegistrationService
{
    public void RegisterUser(??? registration)
    {
        // Do stuff to register user
    }
}

Я пытаюсь понять, что нужно передать в метод RegisterUser. Разумеется, модель просмотра находится под моим веб-приложением (уровень представления), поэтому я не хочу, чтобы это передавалось моей службе.

Итак, я думаю о одной из четырех возможностей:

1) Настройте модель сервиса, которая аналогична, если не идентична, для параметра RegistrationViewModel и используйте это:

public class RegistrationServiceModel
{
    public string Email { get; set; }
    public string Password { get; set; }
}

public class RegistrationService
{
    public void RegisterUser(RegistrationServiceModel registration)
    {
        // Do stuff to register user
    }
}

2) Настройте интерфейс модели и наследуйте ее в моей модели представления и настройте мой метод для приема интерфейса:

public interface IRegistrationModel
{
    string Email;
    string Password;
}

public class RegistrationServiceModel : IRegistrationModel
{
    public string Email { get; set; }
    public string Password { get; set; }
}

public class RegistrationService
{
    public void RegisterUser(IRegistrationModel registration)
    {
        // Do stuff to register user
    }
}

3) Перейдите в объект Account, выполнив сопоставление RegistrationViewModel-to-Account в моем контроллере:

public class RegistrationService
{
    public void RegisterUser(Account account)
    {
        // Do stuff to register user
    }
}

4) Переместите мою модель представления из презентации в уровень домена/службы и передайте ее в метод службы:

public class RegistrationService
{
    public void RegisterUser(RegistrationViewModel account)
    {
        // Do stuff to register user
    }
}

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

Каковы хорошие практики для этого?

Спасибо заранее.

4b9b3361

Ответ 1

Вы никогда не передаете модель просмотра в службу. Служба даже не знает о существовании модели представления, которую вы могли бы определить в своем уровне представления. Служба работает с моделями доменов.
Используйте Auto mapper для сопоставления между моделью модели и моделью домена и наоборот.

Лично я никогда не слышал о моделях обслуживания в DDD (просматривать модели для служб).

Ответ 2

Используйте опцию 3rd, конечно. Как сказал šljaker, служба должна быть не осведомлена о части представления заявки (с которой ваша ViewModel является частью).

Несомненно, не переусердствуйте, включив в себя тонны переходных моделей, таких как RegistrationServiceModel или - еще хуже - IRegistrationModel (последний из них однажды приведет к "взрыву интерфейса" ).

Итак:

  • Имейте объект домена (объект POCO, который сохраняется в Entity Framework или NHibernate или NoRM или что-то еще).
  • Имейте ViewModel, который представляет вашу модель домена в данном контексте. Не стесняйтесь делать ViewModel за действие контроллера, если это необходимо. Преимущество побочных эффектов строгих ViewModels (те, которые составляют 1:1 с вашим представлением) - это полное отсутствие проблем с пересылкой и недопоставлением. Это зависит от конкретной ситуации/вкуса.
  • Используйте атрибуты DataAnnotation с помощью ViewModels для обеспечения базовой проверки (не забудьте также проверить бизнес-правила, но он должен сидеть за проводом - внутри уровня "Службы/Хранилища" ).
  • Не позволяйте службе App когда-либо знать о ViewModels. Создайте экземпляр сущности домена и подайте его в службу вместо (для проверки/сохранения).
  • Используйте AutoMapper в качестве опции для быстрой карты из ваших объектов домена в ViewModels.
  • Карта из входящих ViewModel или FormCollection в вашу сущность либо в действии контроллера, либо в обычном IModelBinder.
  • (необязательно) Я бы рекомендовал следовать Принцип Thunderdome. Это действительно действительно удобное использование ViewModels.

Ответ 3

В этом случае имеет смысл использовать DTO (объект передачи данных). Вы можете создать класс AccountDto на уровне сервиса и использовать его для передачи регистрационных данных в службу. В некоторых случаях он может быть похож на ViewModel, но обычно вы можете показать гораздо больше в своем представлении, чем требуется для создания пользователя. Чтобы проиллюстрировать это, ваш ViewModel, вероятно, по крайней мере будет выглядеть примерно так:

public class RegistrationViewModel
{
    [Required]
    public string Email { get; set; }

    [Required]
    public string Password { get; set; } 

    [Required]
    [Compare("Password")]
    public string RepeatPassword { get; set; } 
}

Пока ваш DTO будет требовать только свойства Email и Password.

public class AccountDto
{
    public string Email { get; set; }
    public string Password { get; set; }
}

Итак, как вы видите, ViewModel содержит только данные, необходимые для View. Логика проверки подлинности электронной почты и пароля выполняется на вашем веб-уровне. Вы используете DTO для получения только электронной почты и пароля для Сервиса. И затем на уровне сервиса вы получите пароль, заселите объект Entity и сохраните значения в базе данных.