условно где в запросе linq - PullRequest
       10

условно где в запросе linq

0 голосов
/ 24 октября 2019

Я хочу вернуть общую сумму из запроса linq, я передаю 2 параметра, которые могут / не могут быть включены в запрос.

OrgId - int

reportType - int

Итак, два вопроса:

  1. Как мне обновить приведенный ниже запрос, чтобы, если OrgId = 0, игнорировать поле организации (Return All)?

  2. LocumClaimTF может быть True / False / Both, если оба игнорируют запрос where для этого поля.

Вот что я сделал до сих пор, это работает, ноЯ хотел бы что-то для эффективности.

            // Using reportType set preferences for LocumClaimTF
            bool locumClaimTF1, locumClaimTF2 = false;
            if (reportType == 0)
            {
                locumClaimTF1 = false;
                locumClaimTF2 = false;
            }
            else if (reportType == 1)
            {
                locumClaimTF1 = true;
                locumClaimTF2 = true;
            }
            else // 2
            {
                locumClaimTF1 = true;
                locumClaimTF2 = false;
            }

            if (OrgID != 0) // Get by OrgID
            {
                return _UoW.ShiftDates.Get(x => x.shiftStartDate >= StartDate && x.shiftEndDate <= EndDate)
             .Where(x => x.Shift.LocumClaimTF == locumClaimTF1 || x.Shift.LocumClaimTF == locumClaimTF2)
             .Where(x => x.Shift.organisationID == OrgID)
             .GroupBy(s => s.assignedLocumID)
                 .Select(g => new dataRowDTO { dataLabel = string.Concat(g.FirstOrDefault().User.FullName), dataCount = g.Count(), dataCurrencyAmount = g.Sum(sd => sd.shiftDateTotal.Value) }
                ).Sum(g=>g.dataCurrencyAmount);
            }
            else // Ignore OrgID - Get ALL Orgs
            {
                return _UoW.ShiftDates.Get(x => x.shiftStartDate >= StartDate && x.shiftEndDate <= EndDate)
               .Where(x => x.Shift.LocumClaimTF == locumClaimTF1 || x.Shift.LocumClaimTF == locumClaimTF2)
               .GroupBy(s => s.assignedLocumID)
                  .Select(g => new dataRowDTO { dataLabel = string.Concat(g.FirstOrDefault().User.FullName), dataCount = g.Count(), dataCurrencyAmount = g.Sum(sd => sd.shiftDateTotal.Value) }
                  ).Sum(g => g.dataCurrencyAmount);
            }

Я использую EF с шаблоном единицы работы, чтобы получить данные от

1 Ответ

1 голос
/ 25 октября 2019

Несколько вещей приходят на ум, сверху вниз:

Для обработки логических значений

bool locumClaimTF1 = (reportType == 1 || reportType == 2);
bool locumClaimTF2 = (reportType == 1);

Из того, что я прочитал в запросе, если тип отчета равен 1 или2, вы хотите, чтобы флаг LocumClaimTF Shift должен иметь значение True. Если это так, то вы можете забыть логические флаги и просто использовать reportType в своем состоянии.

Далее, для составления запроса вы можете условно составить предложения where. Это хорошая вещь в беглом синтаксисе Linq. Тем не менее, давайте временно начнем с обычного DbContext, а не с UoW, потому что это создаст некоторые сложности и вопросы, которые вам нужно будет рассмотреть. (Я расскажу об этом ниже)

using (var context = new ApplicationDbContext()) // <- insert your DbContext here...
{
    var query = context.ShiftDates
       .Where(x => x.shiftStartDate >= StartDate 
           && x.shiftEndDate <= EndDate);
    if (reportType == 1 || reportType == 2)
       query = query.Where(x.Shift.LocumClaimTF);
    if (OrgId > 0)
       query = query.Where(x => x.Shift.organisationID == OrgID);

    var total = query.GroupBy(s => s.assignedLocumID)
        .Select(g => new dataRowDTO 
        { 
           dataLabel = tring.Concat(g.FirstOrDefault().User.FullName), 
           dataCount = g.Count(), 
           dataCurrencyAmount = g.Sum(sd => sd.shiftDateTotal.Value) 
        })
        .Sum(g=>g.dataCurrencyAmount);
}

Теперь это здесь не имеет никакого смысла. Почему вы сталкиваетесь с проблемами группировки, подсчета и суммирования данных, чтобы просто суммировать полученные суммы? Я подозреваю, что вы скопировали существующий запрос, который выбирал DTO для сгруппированных результатов. Если вам не нужны сгруппированные результаты, вам нужно просто итоги. Поэтому в этом случае покончи с группировкой и просто возьмите сумму всех применимых записей:

    var total = query.Sum(x => x.shiftDateTotal.Value);

Таким образом, все это будет выглядеть примерно так:

using (var context = new ApplicationDbContext()) // <- insert your DbContext here...
{
    var query = context.ShiftDates
       .Where(x => x.shiftStartDate >= StartDate 
           && x.shiftEndDate <= EndDate);
    if (reportType == 1 || reportType == 2)
       query = query.Where(x.Shift.LocumClaimTF);
    if (OrgId > 0)
       query = query.Where(x => x.Shift.organisationID == OrgID);

    var total = query.Sum(x => x.shiftDateTotal.Value);
    return total;
}

Назад кЕдиница работы: Основное соображение при использовании этого шаблона - убедиться, что этот вызов Get обязательно должен вернуть обратно IQueryable<TEntity>. Если он возвращает что-то еще, например IEnumerable<TEntity>, то вы столкнетесь с серьезными проблемами производительности, так как он будет возвращать материализованные списки объектов, загруженных в память, а не что-то, что вы можете расширить для построения эффективных запросов к базе данных. Если метод Get не возвращает IQueryable или содержит такие методы, как ToList, где-либо внутри него, за которым следует AsQueryable(), поговорите с остальной частью команды разработчиков, потому что вы буквально стоите над кодом/ EF эквивалент наземной мины. Если он возвращает IQueryable<TEntity> (IQueryable<ShiftDate> в данном случае), то вы можете подставить его обратно в приведенный выше запрос:

var query = _UoW.ShiftDates.Get(x => x.shiftStartDate >= StartDate && x.shiftEndDate <= EndDate);
if (reportType == 1 || reportType == 2)
   query = query.Where(x.Shift.LocumClaimTF);
if (OrgId > 0)
   query = query.Where(x => x.Shift.organisationID == OrgID);

var total = query.Sum(x => x.shiftDateTotal.Value);
return total;
...