【问题标题】:Query handlers in CQRS architectural patternCQRS 架构模式中的查询处理程序
【发布时间】:2020-06-17 23:54:29
【问题描述】:

我从 CQRS 开始,我想我不太确定如何(或者是否可以这样做)添加一个可以对最终查询的结果进行过滤和排序的查询。 例如:

public partial class GetParticipantListQuery : IRequest<IList<ParticipantDto>>
{
    public Expression<Func<ParticipantDto, bool>> Filter { get; set; } = null;
    public Func<IQueryable<ParticipantDto>, IQueryable<ParticipantDto>> OrderBy { get; set; } = null;
}

然后在处理程序中将过滤和排序应用于数据库中的相应结果 这是一个不错的选择吗?我怎样才能在我的查询中实现这种事情? 我的目标是避免为我需要的每个过滤器创建一个查询,例如“GetParticipantsByNameQuery”、“GetParticipantsByTeamIdQuery”等等

【问题讨论】:

    标签: c# .net-core entity-framework-core domain-driven-design cqrs


    【解决方案1】:

    您可以传入一个过滤器类,其中包含过滤结果所需的属性。

    例如:

    public class Filter
    {
        //Property Name
        public string Key { get; set; }
        //Property Type eg. string, int, bool
        public string Type { get; set; }
        //Value to filter
        public object Value { get; set; }
    }
    
    var result = from u in _context.Set<T>() select u;
    switch(filter.Type)
    {
        case "string":
            result = result.Where(e => EF.Property<string>(e, filter.Key).Equals((string)filter.Value));
    }
    

    这只是一个字符串类型的例子,你可以在 switch 块中添加自己的类型来过滤其他类型。

    【讨论】:

    • 感谢您的建议,我已经实现了类似于您的评论的解决方案
    【解决方案2】:

    我接近查询端的方式如下:-

    为了不与我的域冲突,我有一个代表我的查询对象的命名空间。

    域可能是这样的:

    namespace Product
    {
        public class Order
        {
            public Guid Id { get; }
            public DateTime RegisteredDate { get; }
    
            public Order(Guid id, DateTime registeredDate)
            {
                Id = id;
                RegisteredDate = registeredDate;
            }
        }
    }
    

    读取模型看起来像这样(注意嵌套的 Specification 类):

    namespace Product.DataAccess.Query
    {
        public class Order
        {
            public class Specification
            {
                public Guid? Id { get; private set; }
                public DateTime? RegisteredDateStart { get; private set; }
                public DateTime? RegisteredDateEnd { get; private set; }
    
                public Specification WithId(Guid id)
                {
                    Id = id;
    
                    return this;
                }
    
                public Specification WithRegisteredDateStart(DateTime registeredDateStart)
                {
                    RegisteredDateStart = registeredDateStart;
    
                    return this;
                }
    
                public Specification WithRegisteredDateEnd(DateTime registeredDateEnd)
                {
                    RegisteredDateEnd = registeredDateEnd;
    
                    return this;
                }
            }
    
            public Guid Id { get; set; }
            public DateTime RegisteredDate { get; set; }
        }
    }
    

    在我的查询层中,我传递了规范,然后查询层可以使用规范值构造查询:

    namespace Product.DataAccess
    {
        public interface IOrderQuery
        {
            IEnumerable<Query.Order> Search(Query.Order.Specification specification);
            int Count(Query.Order.Specification specification);
        }
    }
    

    通过这种方式,您可以将明确的要求传递给查询层,并在需要更多查询选项时重构规范类和查询实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-03
      • 1970-01-01
      相关资源
      最近更新 更多