Где проверить почту пользователя еще не существует? - PullRequest
4 голосов
/ 05 августа 2009

У меня есть объект учетной записи, который создает пользователя, как так;

public class Account
{
    public ICollection<User> Users { get; set; }

    public User CreateUser(string email)
    {
        User user = new User(email);
        user.Account = this;
        Users.Add(user);
    }
}

В моем слое обслуживания при создании нового пользователя я вызываю этот метод. Однако существует правило, согласно которому электронная почта пользователей ДОЛЖНА быть уникальной для учетной записи, так куда же это приведет? Для меня это должно идти в метод CreateUser с дополнительной строкой, которая просто проверяет, является ли электронная почта уникальной для учетной записи.

Однако, если бы это было сделано, тогда ВСЕ пользователи для этой учетной записи должны были бы быть загружены, и для меня это немного накладные расходы. Было бы лучше запросить в базе данных электронную почту пользователей - но для этого в методе потребуется хранилище в объекте account, не так ли? Возможно, тогда ответ будет при загрузке учетной записи из репозитория вместо выполнения;

var accountRepository.Get(12);
//instead do
var accountRepository.GetWithUserLoadedOnEmail(12, "someone@example.com");

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

Это работает? Что бы вы сделали?

Я использую NHibernate в качестве ORM.

Ответы [ 3 ]

1 голос
/ 06 августа 2009

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

Во-вторых, вы поставили метку DDD на эти вопросы, поэтому я отвечу на нее DDD. Мне кажется, вам нужен доменный сервис или фабрика. После того как вы переместили этот код в доменную службу или фабрику, вы можете вставить в него UserRepository и вызвать его, чтобы узнать, существует ли уже пользователь с таким адресом электронной почты.

Примерно так:

public class CreateUserService
{
private readonly IUserRepository userRepository;

public CreateUserService(IUserRepository userRepository)
{
    this.userRepository = userRepository;
}

public bool CreateUser(Account account, string emailAddress)
{
    // Check if there is already a user with this email address
    User userWithSameEmailAddress = userRepository.GetUserByEmailAddress(emailAddress);
    if (userWithSameEmailAddress != null)
    {
        return false;
    }

    // Create the new user, depending on you aggregates this could be a factory method on Account
    User newUser = new User(emailAddress);
    account.AddUser(newUser);
    return true;
}
}

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

1 голос
/ 05 августа 2009

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

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

public User CreateUser(string email)
{
    try
    {
       User user = new User(email);
       user.Account = this;
       user.Insert();
    catch (SqlException e)
    {
      // It would be best to check for the exception code from your db...
      return null;
    }
}
0 голосов
/ 05 августа 2009

Учитывая, что «правило о том, что электронная почта пользователя ДОЛЖНА быть уникальной для учетной записи», тогда самое важное - указать в схеме базы данных, что электронная почта уникальна, так что INSERT базы данных потерпит неудачу, если электронная почта дублируется .

Вы, вероятно, не можете запретить двум пользователям добавлять одно и то же электронное письмо почти одновременно, поэтому следующее: код должен обрабатывать (изящно) ошибку INSERT, вызванную приведенным выше.

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

...