CQRS 架构模式中的查询处理程序
Query handlers in CQRS architectural pattern
我从 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" 等等
您可以传入一个过滤器 class,其中包含过滤结果所需的属性。
例如:
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));
}
这只是字符串类型的示例,您可以在开关块中添加自己的类型以过滤其他类型。
我处理查询端的方式如下:-
为了不与我的域冲突,我有一个代表我的查询对象的命名空间。
域名可能是这样的:
namespace Product
{
public class Order
{
public Guid Id { get; }
public DateTime RegisteredDate { get; }
public Order(Guid id, DateTime registeredDate)
{
Id = id;
RegisteredDate = registeredDate;
}
}
}
读取模型看起来像这样(注意嵌套的Specification
class):
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);
}
}
通过这种方式,您可以将明确的要求传递给查询层,并在需要进一步查询选项时重构您的规范 class 和查询实现。
我从 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" 等等
您可以传入一个过滤器 class,其中包含过滤结果所需的属性。
例如:
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));
}
这只是字符串类型的示例,您可以在开关块中添加自己的类型以过滤其他类型。
我处理查询端的方式如下:-
为了不与我的域冲突,我有一个代表我的查询对象的命名空间。
域名可能是这样的:
namespace Product
{
public class Order
{
public Guid Id { get; }
public DateTime RegisteredDate { get; }
public Order(Guid id, DateTime registeredDate)
{
Id = id;
RegisteredDate = registeredDate;
}
}
}
读取模型看起来像这样(注意嵌套的Specification
class):
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);
}
}
通过这种方式,您可以将明确的要求传递给查询层,并在需要进一步查询选项时重构您的规范 class 和查询实现。