Многоразовое выражение Linq (для передачи в несколько предложений .Where в разных частях проекта) - PullRequest
0 голосов
/ 08 мая 2020

У меня есть следующий запрос linq.

 var entities = await _context.Events
                .Include(x => x.Category)
                .Include(x => x.Owner)
                .Where(x =>
                    x.OwnerId == request.OwnerId && (
                        x.DateType == 1 && x.EndDateTimeUtc >= DateTime.UtcNow ||
                        x.DateType == 2 && x.Month >= DateTime.UtcNow.Month && x.Year >= DateTime.UtcNow.Year ||
                        x.Year >= DateTime.UtcNow.Year ||
                        x.DateType == 3 && x.Quarter >= quarter && x.Year >= DateTime.UtcNow.Year ||
                        x.Year >= DateTime.UtcNow.Year
                    ))
                .ToListAsync(cancellationToken);

Я бы хотел, чтобы выражение в предложении .Where было функцией / переменной, которую я могу настроить где-нибудь еще и просто передать ее в where статьи. У меня есть несколько запросов, для которых требуются эти очень специфические c условия, поэтому я хотел бы создать его в одном месте и передавать вместо того, чтобы копировать и вставлять.

Функция, которую мне нужно создать, должна принимать 2 параметра (один для request.OwnerId и один для Quarter), остальные генерируются из полей date / db

ПРИМЕЧАНИЕ: часть запроса основана на поле Speci c, несколько других условий применяются, только если DateType является спецификацией c число (1-3)

Ответы [ 3 ]

3 голосов
/ 08 мая 2020

Вы можете создать метод расширения для IQueryable<Event> следующим образом:

public static class EventExtension
{
  public static IQueryable<Event> GetFiltered(this IQueryable<Event> query, Int32 ownerId, Int32 quarter)
  {
    return query.Where(x =>
      x.OwnerId == ownerId && (
        x.DateType == 1 && x.EndDateTimeUtc >= DateTime.UtcNow ||
        x.DateType == 2 && x.Month >= DateTime.UtcNow.Month && x.Year >= DateTime.UtcNow.Year ||
        x.Year >= DateTime.UtcNow.Year ||
        x.DateType == 3 && x.Quarter >= quarter && x.Year >= DateTime.UtcNow.Year ||
        x.Year >= DateTime.UtcNow.Year
      ));
  }
}

Затем просто вызывайте его отовсюду с помощью

var entities = await _context.Events
     .Include(x => x.Category)
     .Include(x => x.Owner)
     .GetFiltered(request.ownerId, request.quarter)
1 голос
/ 08 мая 2020

Помимо ответов @ TWP и Radik , вы также можете сделать что-то вроде этого:

var ownerId =  request.OwnerId;
var quater = ...;
Expression<Func<Event, bool>> predicate = x =>
                    x.OwnerId == ownerId && (
                        x.DateType == 1 && x.EndDateTimeUtc >= DateTime.UtcNow ||
                        x.DateType == 2 && x.Month >= DateTime.UtcNow.Month && x.Year >= DateTime.UtcNow.Year ||
                        x.Year >= DateTime.UtcNow.Year ||
                        x.DateType == 3 && x.Quarter >= quarter && x.Year >= DateTime.UtcNow.Year ||
                        x.Year >= DateTime.UtcNow.Year
                    )

И передать это так _context.Events.Where(predicate). Вы можете выделить создание выражения в отдельный метод.

1 голос
/ 08 мая 2020

вы можете использовать IQueryable следующим образом

interface IFilter {
    IQueryable<Events> Filter(IQueryable<Events> query, Request request)
}

public class SpecificFilter : IFilter {
    public IQueryable<Events> Filter(IQueryable<Events> query, Request request)
    {
        if(request.ById) {
           query = query.Where(event => event.Id == request.Id);
        }
        return query;
    }
}

, чтобы вы могли иметь список IFilter и применять их к вашему запросу

var query = _context.Events
    .Include(x => x.Category)
    .Include(x => x.Owner);
foreach(var filter in filterList) {
    query = filter.Filter(query, request);
}
var entities = await query;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...