Объекты EF против сервисных моделей и моделей просмотра (MVC) - PullRequest
24 голосов
/ 25 февраля 2011

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

Допустим, у меня есть следующая таблица базы данных, Account:

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
    }
}

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

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

1) Установите модель службы, которая похожа, если не идентична, на RegistrationViewModel, и используйтеthis:

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
    }
}

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

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

Заранее спасибо.

Ответы [ 3 ]

9 голосов
/ 25 февраля 2011

Используйте параметр 3-й , наверняка. Как сказал Шлякер, Сервис не должен знать о представительной части приложения (частью которой является ваша ViewModel).

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

Итак:

  1. Иметь сущность Домена (сущность POCO, которая сохраняется с Entity Framework или NHibernate или NoRM или любым другим).
  2. Имейте ViewModel, который представляет модель вашего домена в данном контексте. Не стесняйтесь делать ViewModel за действие контроллера при необходимости. Побочным эффектом строгих ViewModels (те, которые имеют 1: 1 с вашим View) является полное отсутствие проблем чрезмерной публикации и недостаточной публикации. Это зависит от вашей конкретной ситуации / вкуса.
  3. Используйте атрибуты DataAnnotation с вашими ViewModels для обеспечения базовой проверки (не забывайте проверять и бизнес-правила, но они должны располагаться за проводом - внутри слоя Services / Repositories).
  4. Не сообщайте службе приложений о ViewModels. Создайте экземпляр объекта домена и передайте его в Службу (для проверки / сохранения).
  5. Используйте AutoMapper как опцию для быстрого сопоставления сущностей вашего домена с ViewModels.
  6. Сопоставление входящих ViewModel или FormCollection с вашей сущностью в действии контроллера или в пользовательском IModelBinder.
  7. (опционально). Я бы рекомендовал следовать принципу Thunderdome . Это действительно действительно удобное использование ViewModels.
8 голосов
/ 25 февраля 2011

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

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

3 голосов
/ 25 февраля 2011

В этом случае имеет смысл использовать 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 и сохраняете значения в базе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...