在哪里查看用户电子邮件尚不存在?

Gar*_*eth 5 domain-driven-design

我有一个创建对象的帐户对象,就像这样;

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的服务层中,创建新用户时,我调用此方法。但是,有一个规则,即用户电子邮件对于该帐户必须是唯一的,那么该去哪里呢?对我来说,它应该放在CreateUser方法中,并带有额外的一行,该行仅检查电子邮件对于帐户而言是唯一的。

但是,如果要这样做,则将需要加载该帐户的所有用户,这对我来说似乎有些负担。最好在数据库中查询用户的电子邮件-但在该方法中这样做将需要在account对象中存储一个库,不是吗?答案可能就是从存储库加载帐户而不是这样做。

var accountRepository.Get(12);
//instead do
var accountRepository.GetWithUserLoadedOnEmail(12, "someone@example.com");
Run Code Online (Sandbox Code Playgroud)

然后,该帐户对象仍可以检查Users集合中的电子邮件,并且如果找到该电子邮件对象,则将它急切地装入其中。

这样行吗?你会怎么做?

我正在使用NHibernate作为ORM。

Ste*_*ser 4

首先,我认为您不应该使用异常来处理“正常”业务逻辑,例如检查重复的电子邮件地址。这是一个有据可查的反模式,最好避免。保持对数据库的约束并处理任何重复的异常,因为它们无法避免,但尝试通过检查将它们保持在最低限度。我不建议锁定桌子。

其次,你在这个问题上贴上了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;
}
}
Run Code Online (Sandbox Code Playgroud)

这允许您稍微分离职责并使用域服务来协调事物。希望有帮助!

  • 该服务*位于*领域层,而不*位于服务层。该服务中没有基础设施,它在多个其他域对象之间进行协调。领域服务是 DDD 的重要组成部分,它不仅仅是实体。我只是使用一个简单的布尔返回值来检查唯一的电子邮件地址,所以是的,如果需要,请随意使其更具表现力。 (2认同)