Обработчики запросов в архитектурном шаблоне CQRS - PullRequest
0 голосов
/ 18 июня 2020

Я начинаю с 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» и т. Д. И т. Д.

Ответы [ 2 ]

1 голос
/ 18 июня 2020

Я подхожу к своей стороне запроса следующим образом: -

У меня есть пространство имен, которое представляет мои объекты запроса, чтобы не конфликтовать с моим доменом.

Домен может быть чем-то вот так:

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; }
    }
}

В моем уровне запроса I передайте спецификацию, и уровень запроса может затем построить запрос, используя значения спецификации:

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

Таким образом, у вас есть явное требование, переданное вашему уровню запроса, и вы реорганизуете свой класс спецификации и реализацию запроса когда вам нужны дополнительные параметры запроса.

1 голос
/ 18 июня 2020

Вы можете передать класс фильтра, который содержит необходимые свойства для фильтрации результата.

Например:

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));
}

Это просто пример строкового типа, вы можете добавить ваш собственный тип в блоке переключателя для фильтрации других типов.

...