Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# CQR中的验证和同步命令_C#_Validation_Nhibernate_Cqrs - Fatal编程技术网

C# CQR中的验证和同步命令

C# CQR中的验证和同步命令,c#,validation,nhibernate,cqrs,C#,Validation,Nhibernate,Cqrs,我喜欢在没有事件来源的情况下尝试CQR的想法。 但我不知道如何解决我需要给用户即时反馈的问题 这就是我当前注册的方式(简化为理解) 我用简洁的方式读,用nHibernate写 注册控制器.cs public ActionResult signup(UserCreateModel model) { // model validation (email, password strength etc) if (!ModelState.IsValid

我喜欢在没有事件来源的情况下尝试CQR的想法。 但我不知道如何解决我需要给用户即时反馈的问题

这就是我当前注册的方式(简化为理解) 我用简洁的方式读,用nHibernate写

注册控制器.cs

 public ActionResult signup(UserCreateModel model)
  {
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }

            // use service layer to validate against database and create user  
            var registermodel = _userService.create_user_account(model.username, model.email, model.password);

            // service returns and object with several states  
            if (registermodel.Status == UserRegistrationStatus.Ok)
            {
                // user registered ok, display thank you or whatever
            }

            if (registermodel.Status == UserRegistrationStatus.DuplicatedUsername)
            {
                // duplicated username found, back to form and show errors 
            }

            if (registermodel.Status == UserRegistrationStatus.DuplicatedEmail)
            {
                // duplicated email found, back to form and show errors 
            }

            // get back to form and show errors 
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }
            // validate duplicated email          
            bool is_email_duplicated = _read.user_email_exists(model.email);
                // duplicated email found, back to form and show errors 

            // validate duplicated username          
            bool is_username_duplicated = _read.user_username_exists(model.username);            
                // duplicated username found, back to form and show errors 

            // assume all is perfect and dispatch
            _commandDispatcher.Dispatch(new CreateUserCommand(model.username, model.email, model.password));
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }

            // dispatch and validate inside the handler, abort execution if validation failed
            var command = new CreateUserCommand(model.username, model.email, model.password)

            // attached common feedback object to the command and deal with errors 
            if(command.status == UserRegistrationStatus.DuplicatedUsername)
            {
                // get back to form and show errors 
            } 
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }
            var feedback = _userService.create_user(model.username, model.email, model.password);
            // check for status and return feedback to the user
}
public Feedback create_user(string username, string email, string password)
{
            // validate duplicated email          
            bool is_email_duplicated = _read.user_email_exists(email);
                // duplicated email found, back to form and show errors 

            // validate duplicated username          
            bool is_username_duplicated = _read.user_username_exists(username);            
                // duplicated username found, back to form and show errors 

            // dispatch command
            _commandDispatcher.Dispatch(new CreateUserCommand(username, email, password));
}
哪种方法对CQR最友好? 方法1 注册控制器.cs

 public ActionResult signup(UserCreateModel model)
  {
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }

            // use service layer to validate against database and create user  
            var registermodel = _userService.create_user_account(model.username, model.email, model.password);

            // service returns and object with several states  
            if (registermodel.Status == UserRegistrationStatus.Ok)
            {
                // user registered ok, display thank you or whatever
            }

            if (registermodel.Status == UserRegistrationStatus.DuplicatedUsername)
            {
                // duplicated username found, back to form and show errors 
            }

            if (registermodel.Status == UserRegistrationStatus.DuplicatedEmail)
            {
                // duplicated email found, back to form and show errors 
            }

            // get back to form and show errors 
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }
            // validate duplicated email          
            bool is_email_duplicated = _read.user_email_exists(model.email);
                // duplicated email found, back to form and show errors 

            // validate duplicated username          
            bool is_username_duplicated = _read.user_username_exists(model.username);            
                // duplicated username found, back to form and show errors 

            // assume all is perfect and dispatch
            _commandDispatcher.Dispatch(new CreateUserCommand(model.username, model.email, model.password));
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }

            // dispatch and validate inside the handler, abort execution if validation failed
            var command = new CreateUserCommand(model.username, model.email, model.password)

            // attached common feedback object to the command and deal with errors 
            if(command.status == UserRegistrationStatus.DuplicatedUsername)
            {
                // get back to form and show errors 
            } 
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }
            var feedback = _userService.create_user(model.username, model.email, model.password);
            // check for status and return feedback to the user
}
public Feedback create_user(string username, string email, string password)
{
            // validate duplicated email          
            bool is_email_duplicated = _read.user_email_exists(email);
                // duplicated email found, back to form and show errors 

            // validate duplicated username          
            bool is_username_duplicated = _read.user_username_exists(username);            
                // duplicated username found, back to form and show errors 

            // dispatch command
            _commandDispatcher.Dispatch(new CreateUserCommand(username, email, password));
}
如果我需要在系统中的其他地方执行相同的验证(我会复制代码),该怎么办

我考虑过创建ValidationService

若命令因某种原因“爆炸”,用户将得到错误的反馈,该怎么办

方法2 注册控制器.cs

 public ActionResult signup(UserCreateModel model)
  {
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }

            // use service layer to validate against database and create user  
            var registermodel = _userService.create_user_account(model.username, model.email, model.password);

            // service returns and object with several states  
            if (registermodel.Status == UserRegistrationStatus.Ok)
            {
                // user registered ok, display thank you or whatever
            }

            if (registermodel.Status == UserRegistrationStatus.DuplicatedUsername)
            {
                // duplicated username found, back to form and show errors 
            }

            if (registermodel.Status == UserRegistrationStatus.DuplicatedEmail)
            {
                // duplicated email found, back to form and show errors 
            }

            // get back to form and show errors 
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }
            // validate duplicated email          
            bool is_email_duplicated = _read.user_email_exists(model.email);
                // duplicated email found, back to form and show errors 

            // validate duplicated username          
            bool is_username_duplicated = _read.user_username_exists(model.username);            
                // duplicated username found, back to form and show errors 

            // assume all is perfect and dispatch
            _commandDispatcher.Dispatch(new CreateUserCommand(model.username, model.email, model.password));
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }

            // dispatch and validate inside the handler, abort execution if validation failed
            var command = new CreateUserCommand(model.username, model.email, model.password)

            // attached common feedback object to the command and deal with errors 
            if(command.status == UserRegistrationStatus.DuplicatedUsername)
            {
                // get back to form and show errors 
            } 
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }
            var feedback = _userService.create_user(model.username, model.email, model.password);
            // check for status and return feedback to the user
}
public Feedback create_user(string username, string email, string password)
{
            // validate duplicated email          
            bool is_email_duplicated = _read.user_email_exists(email);
                // duplicated email found, back to form and show errors 

            // validate duplicated username          
            bool is_username_duplicated = _read.user_username_exists(username);            
                // duplicated username found, back to form and show errors 

            // dispatch command
            _commandDispatcher.Dispatch(new CreateUserCommand(username, email, password));
}
基本上在处理程序内部,我欺骗和验证(向nHibernate repo添加额外的方法)

方法3 与第一种方法类似,但将验证和分派封装在UserService中

注册控制器.cs

 public ActionResult signup(UserCreateModel model)
  {
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }

            // use service layer to validate against database and create user  
            var registermodel = _userService.create_user_account(model.username, model.email, model.password);

            // service returns and object with several states  
            if (registermodel.Status == UserRegistrationStatus.Ok)
            {
                // user registered ok, display thank you or whatever
            }

            if (registermodel.Status == UserRegistrationStatus.DuplicatedUsername)
            {
                // duplicated username found, back to form and show errors 
            }

            if (registermodel.Status == UserRegistrationStatus.DuplicatedEmail)
            {
                // duplicated email found, back to form and show errors 
            }

            // get back to form and show errors 
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }
            // validate duplicated email          
            bool is_email_duplicated = _read.user_email_exists(model.email);
                // duplicated email found, back to form and show errors 

            // validate duplicated username          
            bool is_username_duplicated = _read.user_username_exists(model.username);            
                // duplicated username found, back to form and show errors 

            // assume all is perfect and dispatch
            _commandDispatcher.Dispatch(new CreateUserCommand(model.username, model.email, model.password));
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }

            // dispatch and validate inside the handler, abort execution if validation failed
            var command = new CreateUserCommand(model.username, model.email, model.password)

            // attached common feedback object to the command and deal with errors 
            if(command.status == UserRegistrationStatus.DuplicatedUsername)
            {
                // get back to form and show errors 
            } 
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }
            var feedback = _userService.create_user(model.username, model.email, model.password);
            // check for status and return feedback to the user
}
public Feedback create_user(string username, string email, string password)
{
            // validate duplicated email          
            bool is_email_duplicated = _read.user_email_exists(email);
                // duplicated email found, back to form and show errors 

            // validate duplicated username          
            bool is_username_duplicated = _read.user_username_exists(username);            
                // duplicated username found, back to form and show errors 

            // dispatch command
            _commandDispatcher.Dispatch(new CreateUserCommand(username, email, password));
}
userservice.cs

 public ActionResult signup(UserCreateModel model)
  {
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }

            // use service layer to validate against database and create user  
            var registermodel = _userService.create_user_account(model.username, model.email, model.password);

            // service returns and object with several states  
            if (registermodel.Status == UserRegistrationStatus.Ok)
            {
                // user registered ok, display thank you or whatever
            }

            if (registermodel.Status == UserRegistrationStatus.DuplicatedUsername)
            {
                // duplicated username found, back to form and show errors 
            }

            if (registermodel.Status == UserRegistrationStatus.DuplicatedEmail)
            {
                // duplicated email found, back to form and show errors 
            }

            // get back to form and show errors 
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }
            // validate duplicated email          
            bool is_email_duplicated = _read.user_email_exists(model.email);
                // duplicated email found, back to form and show errors 

            // validate duplicated username          
            bool is_username_duplicated = _read.user_username_exists(model.username);            
                // duplicated username found, back to form and show errors 

            // assume all is perfect and dispatch
            _commandDispatcher.Dispatch(new CreateUserCommand(model.username, model.email, model.password));
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }

            // dispatch and validate inside the handler, abort execution if validation failed
            var command = new CreateUserCommand(model.username, model.email, model.password)

            // attached common feedback object to the command and deal with errors 
            if(command.status == UserRegistrationStatus.DuplicatedUsername)
            {
                // get back to form and show errors 
            } 
}
public ActionResult signup(UserCreateModel model)
{
            // model validation (email, password strength etc)
            if (!ModelState.IsValid)
            {
                // get back to form and show errors 
            }
            var feedback = _userService.create_user(model.username, model.email, model.password);
            // check for status and return feedback to the user
}
public Feedback create_user(string username, string email, string password)
{
            // validate duplicated email          
            bool is_email_duplicated = _read.user_email_exists(email);
                // duplicated email found, back to form and show errors 

            // validate duplicated username          
            bool is_username_duplicated = _read.user_username_exists(username);            
                // duplicated username found, back to form and show errors 

            // dispatch command
            _commandDispatcher.Dispatch(new CreateUserCommand(username, email, password));
}

我喜欢这种方法,但我觉得它将成为一种Baklava代码。

通常在使用CQR时,您希望使用乐观的方法

这个想法是在发出命令之前验证您的输入(可能是针对字符串格式或电子邮件的唯一性的简单验证)

显然,在实际生成
命令
时,您将仔细检查数据,以确保
命令
处于有效和安全的状态(这同样适用于所有其他对象)

基于此,您可以假设您的
命令将正确调度,并使用乐观的方法向用户提供积极的反馈

如果您的
CommandHandler
无法处理您的
命令
可能会引发
异常
,您可以捕获并相应地通知用户


以Messenger/Facebook为例,当您键入并发送消息时,UI会让您认为一切都进行得很顺利,消息也已发送,但是,如果发生什么情况,您的UI将回滚。

正如您所看到的,有多种可能的方法来处理命令的发送。有时,您会看到人们严格遵守从命令处理程序返回void,但也有ACK/NACK(已确认/未确认)响应的方法

我这样做的方式是,我的命令处理程序实现的Dispatch()方法将始终返回两种可能的状态之一,即ACK或NACK。这告诉我,我试图发送的命令是否被认为处于可以应用于系统的状态。然而,与ACK/NACK的简单枚举不同,每个命令都能够返回确认类。该类包含一个状态(ACK/NACK),以及一个或多个命令失败。这样,如果我有一个ACK,我知道该命令已收到,我可以假设它将被处理。另一方面,如果我得到一个NACK,我有一个失败,我可以格式化并呈现给用户。但是,我在任何时候都不会返回任何与发送后状态相关的信息。我报告的故障(同一个命令可能有多个故障)完全基于命令中的数据,与应用于系统的数据无关

这一切与你的第三个例子密切相关。上述方法的不同之处在于,封装故障和状态将允许您使用命令呈现/跟踪所有问题,而不是第一个故障

下面是我用来完成此任务的简单类/枚举

确认

namespace Commands
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// Provides an ACK/NACK for an issued <see cref="Command" />.  Can represent one of two states,
    /// being either Acknowledged or Not Acknowledged, along with the ability to track unhandled faults.
    /// </summary>
    /// <remarks>
    /// ACK/NACK implies a synchronous command execution.  Asynchronous commands, while more rarely used,
    /// should represent the concept of command acknowledgement through events.
    /// </remarks>
    public sealed class Acknowledgement
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="Acknowledgement"/> class.
        /// </summary>
        /// <remarks>
        /// This is representative of an <see cref="AcknowledgementState.Acknowledged" /> state, with
        /// no command failures nor faults.
        /// </remarks>
        public Acknowledgement()
        {
            this.State = AcknowledgementState.Acknowledged;
            this.CommandFailures = new List<CommandValidationFailure>();    
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Acknowledgement"/> class.
        /// </summary>
        /// <param name="failures">The command validation failures that led to NACK.</param>
        /// <remarks>
        /// This is representative of a <see cref="AcknowledgementState.NotAcknowledged" /> state, with
        /// at least one command validation failure and no fault.
        /// </remarks>
        public Acknowledgement(IEnumerable<CommandValidationFailure> failures)
        {
            this.State = AcknowledgementState.NotAcknowledged;
            this.CommandFailures = failures;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Acknowledgement"/> class.
        /// </summary>
        /// <param name="fault">The fault that led to the NACK.</param>
        /// <remarks>
        /// This is representative of a <see cref="AcknowledgementState.NotAcknowledged" /> state, with
        /// a fault and no command validation failures.
        /// </remarks>
        public Acknowledgement(Exception fault)
        {
            this.State = AcknowledgementState.NotAcknowledged;
            this.Fault = fault;
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets the command failures that led to a NACK, if any.
        /// </summary>
        /// <value>
        /// The command failures, if present.
        /// </value>
        public IEnumerable<CommandValidationFailure> CommandFailures { get; }

        /// <summary>
        /// Gets the fault that led to a NACK, if present.
        /// </summary>
        /// <value>
        /// The fault.
        /// </value>
        public Exception Fault { get; }

        /// <summary>
        /// Gets a value indicating whether this <see cref="Acknowledgement" /> is backed by a fault.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is reflective of a fault; otherwise, <c>false</c>.
        /// </value>
        public bool IsFaulted => this.Fault != null;

        /// <summary>
        /// Gets a value indicating whether this <see cref="Acknowledgement" /> is backed by command validation failures.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is reflective of command failures; otherwise, <c>false</c>.
        /// </value>
        public bool IsInvalid => this.CommandFailures != null && this.CommandFailures.Any();

        /// <summary>
        /// Gets the state of this instance, in terms of an ACK or NACK.
        /// </summary>
        /// <value>
        /// The state representation.
        /// </value>
        public AcknowledgementState State { get; }

        #endregion
    }
}
名称空间命令
{
使用制度;
使用System.Collections.Generic;
使用System.Linq;
/// 
///为已发布状态提供ACK/NACK。可以表示两种状态之一,
///被确认或未被确认,以及跟踪未处理故障的能力。
/// 
/// 
///ACK/NACK意味着同步命令执行。异步命令虽然很少使用,
///应表示通过事件确认命令的概念。
/// 
公开密封类确认函
{
#区域构造函数
/// 
///初始化类的新实例。
/// 
/// 
///这是一个国家的代表,具有
///没有命令失败或错误。
/// 
公开承认
{
this.State=AcknowledgementState.Acknowledged;
this.CommandFailures=新列表();
}
/// 
///初始化类的新实例。
/// 
///导致NACK的命令验证失败。
/// 
///这是一个国家的代表,具有
///至少有一个命令验证失败且无故障。
/// 
公开确认(IEnumerable failures)
{
this.State=AcknowledgementState.NotAcknowledged;
this.CommandFailures=失败;
}
/// 
///初始化类的新实例。
/// 
///导致NACK的故障。
/// 
///这是一个国家的代表,具有
///出现故障且没有命令验证失败。
/// 
公开承认(例外错误)
{
this.State=AcknowledgementState.NotAcknowledged;
该故障=故障;
}
#端区
#区域公共财产
/// 
///获取导致NACK的命令失败(如果有)。
/// 
/// 
///命令失败(如果存在)。
/// 
公共IEnumerable命令失败{get;}
/// 
///获取导致NACK的故障(如果存在)。
///