2012-07-18 56 views
2

我试图围绕CQRS我的头。我从提供的代码示例here中绘制。请温柔我对这种模式很陌生。CQRS - 当命令无法解析到域

我正在查看登录方案。我喜欢这个场景,因为它在我读过的任何例子中都没有被真正展示过。在这种情况下,我不知道用户的聚合ID是什么,或者即使有一个,因为我开始的是用户名和密码。

在fohjin例子事件总是从域发射(如果需要)和命令处理程序调用上的域一些方法。但是,如果用户登录无效,我没有任何域可以调用任何东西。同样,大多数(如果不是全部)在fohjin项目中定义的基本Command/Event类都传递一个聚集ID。

在事件的情况下LogonFailure我可能要更新LogonAudit报告。

所以我的问题是:如何处理命令不解析为一个特定的汇总?这将如何流动?

public void Execute(UserLogonCommand command) 
    { 
     var user = null;//user looked up by username somehow, should i query the report database to resolve the username to an id? 

     if (user == null || user.Password != command.Password) 
      ;//What to do here? I want to raise an event somehow that doesn't target a specific user 
     else 
      user.LogonSuccessful(); 
    } 
+1

我在CQRS + ES上写了一个MembershipProvider,如果你[想看一看](https://github.com/Iridio/CQRS-ES_MembershipProvider) – Iridio 2012-07-20 11:49:09

+0

谢谢,这对我有帮助。它似乎忽略登录尝试的记录,但不匹配现有的用户名。这是我的问题的核心 – Sam 2012-07-24 04:38:28

+0

失败的尝试存储在Faliedpassword尝试和FailedPasswordQuestionAndAnswerAtwerpt和相对日期时间 – Iridio 2012-07-24 06:37:12

回答

3

您应该考虑到,大多数情况下CQRS和DDD仅适用于系统的某些部分。使用CQRS概念对整个系统进行建模是非常罕见的 - 它最适合具有复杂业务领域的部分,并且我不会在特别复杂的业务场景中调用登录用户。事实上,在大多数情况下,它根本不是与商业相关的。当用户已被识别时,实际的业务域开始。

另一件事要记住的是,由于最终一致性是非常有益的,检查的多,我们可以仅使用查询侧,没有事件产生的任何命令/事件。然而

假设,即约成功/失败的用户登录功能的信息是有意义的我想你的情况有以下步骤

  1. 用户提供名和密码
  2. 名称/密码对一些模型验证这种查询数据库的
  3. 当提供的凭证(用户ID)执行有效RegisterValidUserCommand导致合适的事件
  4. 如果提供的凭据无效 RegisterInvalidCredentialsCo命令(providedUserName)被执行导致适当的事件

问题是检查用户凭证不一定是业务域的一部分。

不过,还有另一个相关的概念,其中不是每个命令或事件必须是业务 - 相关的,因此可以处理不需要聚集到加载事件。

例如你想改变的数据就是信息只,绝不会影响您的系统的企业经营理念,如对人的性别信息(再次,假设它没有业务含义)。

在这种情况下,当您处理SetPersonSexCommand时,实际上不需要加载聚合,因为该信息甚至不必位于实体上,而是创建PersonSexSetEvent,注册它并发布,以便查询端可以将其投影到屏幕/ raport。

+0

同意。虽然用户访问域可能是你想要建模的东西。 – 2012-07-19 15:01:31

+0

因此,您的建议是避免查询除命令内的写入存储之外的其他任何内容?我想我需要一个单独的抽象/事件存储来处理没有针对特定聚合的事件(因为我仍然希望通过事件采购来重现失败)。我认为这个登录场景最符合你的第二个例子,它对实体没有任何意义。我只是对在哪里进行身份验证检查感到困惑。感谢您的回复。 – Sam 2012-07-20 00:46:16

+2

使用cqrs对此进行建模的另一个问题是在命令和/或事件中记录明文密码 – Kimble 2012-07-31 22:27:48