Фильтрация запросов DDD, CQRS и Mediatr - PullRequest
0 голосов
/ 30 ноября 2018

Я работаю над проектом по шаблону CQRS и Mediatr.

У меня есть объект, настроенный так

    public class Order
{
    public Guid OrderId { get; set; }

    public Guid CreatedByUserId { get; set; }

    public Guid? AcceptedByUserId { get; set; }

    public string Registration { get; set; }

    public string Description { get; set; }

    public User CreatedByUser { get; set; }
    public User AcceptedByUser { get; set; }
}

Когда я пишу свои 2 запроса, GetAllOrdersCreatedByUser & GetAllOrdersAcceptedByUser allкод практически одинаковый.

Единственное исключение - запрос Created, my where находится на CreatedByUserId, а запрос Accepted, где находится AcceptedByUserId

GetAllOrdersAcceptedByUser: -

        public async Task<OrderAcceptedByUserListViewModel> Handle(GetAllOrdersAcceptedByUserQuery request, CancellationToken cancellationToken)
    {
        var model = new OrderAcceptedByUserListViewModel
        {
            Orders = await _context.Order
            .Where(x => x.AcceptedByUserId == request.UserId)
            .Select(OrderDto.Projection)
            .OrderBy(o => o.Registration)
            .ToListAsync(cancellationToken)
        };

        return model;
    }

GetAllOrdersCreatedByUser: -

        public async Task<OrderCreatedByUserListViewModel> Handle(GetAllOrdersCreatedByUserQuery request, CancellationToken cancellationToken)
    {
        var model = new OrderCreatedByUserListViewModel
        {
            Orders = await _context.Order
            .Where(x => x.CreatedByUserId == request.UserId)
            .Select(OrderDto.Projection)
            .OrderBy(o => o.Registration)
            .ToListAsync(cancellationToken)
        };

        return model;
    }

Это правильная реализация или объективно лучше иметь 1 запрос, который может выполнять обе функции в зависимости от того, как еговызывается с контроллера?

Редактировать: Добавлены лучшие теги

Ответы [ 3 ]

0 голосов
/ 30 ноября 2018

Прежде всего, классы слияния GetAllOrdersCreatedByUserQuery и GetAllOrdersAcceptedByUserQuery

См. Следующий класс для справки:

public class GetAllOrdersByUserQuery :  : IRequest<OrdeListViewModel>
{
    // if OrderAcceptedByUser is true else OrderCreatedByUser = false
    public bool AcceptedOrCreatedBit { get; set; } 
    public string UserId { get; set; }
}

А также посмотрите на модель для OrderCreatedByUserListViewModel and OrderCreatedByUserListViewModel

См. Следующую модель представления для справки:

public class OrdeListViewModel
{
    public List<Order> Orders { get; set; }
}

И, наконец, ваш метод обработки MediatR должен выглядеть следующим образом:

public async Task<OrdeListViewModel> Handle(GetAllOrdersByUserQuery request, CancellationToken cancellationToken)
{
    OrdeListViewModel model = new OrdeListViewModel();
    if (request.AcceptedOrCreatedBit) // true for OrderAcceptedByUser
    {

            model.Orders = await _context.Order
            .Where(x => x.AcceptedByUserId == request.UserId)
            .Select(OrderDto.Projection)
            .OrderBy(o => o.Registration)
            .ToListAsync(cancellationToken)

    }
    else // false for OrderCreatedByUser
    {

            model.Orders = await _context.Order
            .Where(x => x.CreatedByUserId == request.UserId)
            .Select(OrderDto.Projection)
            .OrderBy(o => o.Registration)
            .ToListAsync(cancellationToken)

    }

    return model;
}
0 голосов
/ 02 декабря 2018

Вы можете применить шаблон спецификации к запросам, т. Е. Один запрос с предикатом в качестве аргумента.

Но DDD поощряет использование вездесущего языка, и если ваши пользователи говорят не с помощью предикатов, а с именами конкретных методов, я бы предложил пользователю 2 запроса, а затем, если вы не хотите повторять кодоба запроса будут вызывать общий запрос с использованием предикатов.

0 голосов
/ 30 ноября 2018

Запросы могут остаться отдельными (поэтому они следуют SOLID), и вы можете избежать дублирования кода другими способами.Возможно, попробуйте извлечь повторяющуюся часть запроса, чтобы получить заказы без их фильтрации, сначала используя where в методе virtual, а затем отфильтровать их в соответствующих запросах.

...