linq查询中的条件where

conditional where in linq query

我想 return 来自 linq 查询的总和,我传入了 2 个 may/may 不包含在查询中的参数。

OrgId - 整数

报告类型 - 整数

所以两个问题:

  1. 如何更新下面的查询,以便在 OrgId = 0 时忽略组织字段(Return 全部)?

  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 来获取数据 frm

我想到了一些事情,从上到下:

用于处理布尔值

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

根据我在查询中读到的内容,如果报告类型为 1 或 2,您希望 Shift 的 LocumClaimTF 标志必须为 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 调用绝对必须 return 返回 IQueryable<TEntity>。如果它 return 是其他任何东西,例如 IEnumerable<TEntity> 那么您将面临严重的性能问题,因为它将 returning 加载到内存的实体化列表而不是您需要的东西可以扩展以构建对数据库的高效查询。如果 Get 方法没有 return IQueryable,或者在其中的任何地方包含诸如 ToList 后跟 AsQueryable() 之类的方法,那么请与其他人谈谈开发团队,因为你真的站在 code/EF 相当于地雷的地方。如果是 return 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;