【问题标题】:How to remove redundant execution paths in a concatenated linq/lambda expression如何删除串联 linq/lambda 表达式中的冗余执行路径
【发布时间】:2019-06-06 18:12:56
【问题描述】:

这是根据条件将这些 linq/lambda 语句连接在一起的最佳方式吗?这样我就不必多次参与同一件事。

我不是专家,但似乎有一些冗余?也许执行路径不是最有效的! 例如。

        var products = context.Products.Select(c => c);

        if (input.DefendantId != null)
        {
            products =
                from p in products
                join pd in context.ProductDefendant
                    on p.Id equals pd.ProductId
                where pd.DefendantId == input.DefendantId
                select p;
        }

        if (input.DefendantCode != null && input.DefendantId == null)
        {
            products =
                from p in products
                join pd in context.ProductDefendant
                    on p.Id equals pd.ProductId
                join d in context.Defendants
                    on pd.DefendantId equals d.Id
                where d.DefendantCode.Any(rp => EF.Functions.Like(d.DefendantCode, "%" + input.DefendantCode + "%"))
                select p;

        }

        if (input.ProductId != null)
        {
            products = products.Where(c => c.Id == input.ProductId);
        }

        if (input.ProductName != null && input.ProductId == null)
        {
            products = products.Where(c => EF.Functions.Like(c.ProductName, "%" + input.ProductName + "%"));
        }

        var productsVM =
            from p in products
            join pd in context.ProductDefendant
                on p.Id equals pd.ProductId
            join d in context.Defendants
                on pd.DefendantId equals d.Id
            select new GetProductsReturnViewModel
            {
                Id = p.Id,
                ProductName = p.ProductName,
                DefendantCode = d.DefendantCode
            };


        switch (input.SortBy + "_" + input.OrderBy)
        {
            case "productName_DESC":
                productsVM = productsVM.OrderByDescending(c => c.ProductName);
                break;
            default:
                productsVM = productsVM.OrderBy(c => c.ProductName);
                break;
        }

        if (input.PageSize != 0)
        {
            productsVM = productsVM.Skip((input.Page - 1) * input.PageSize).Take(input.PageSize);
        }

        return productsVM;

【问题讨论】:

  • 上部的半连接似乎可以从内部查询中移出。除此之外,它看起来确实不错。如果 GetProductsReturnViewModel 不是模型的一部分,您可以考虑缓存它们。
  • 我认为我遇到的问题是,当我有 input.DefendantCode != null && input.DefendantId == null 的条件并且使用该部分时 where 子句很好,但是随后如果使用条件 input.ProductName != null && input.ProductId == null ,则 where 子句将被覆盖。所以基本上如果两个条件都满足,我需要两个 where 子句,目前只使用一个。我只能看输出窗口,看看正在运行什么 sql
  • 如何覆盖该子句?应用于过滤的 IQueryable 的 where 应导致包含两个条件(AND 连接)的 IQueryable

标签: c# entity-framework linq lambda


【解决方案1】:

我会保留每个join 第一次出现的结果,并将连接结果向下传递。

var ProdsProdDef = from p in context.Products
                   join pd in context.ProductDefendant on p.Id equals pd.ProductId
                   select new { p, pd };

if (input.DefendantId != null) {
    ProdsProdDef = from ppd in ProdsProdDef
                   where ppd.pd.DefendantId == input.DefendantId
                   select ppd;
}

var ProdsProdDefDef = from ppd in ProdsProdDef
                      join d in context.Defendants on ppd.pd.DefendantId equals d.Id
                      select new { ppd.p, ppd.pd, d };

if (input.DefendantCode != null && input.DefendantId == null) {
    ProdsProdDefDef = from ppdd in ProdsProdDefDef
                      where ppdd.d.DefendantCode.Any(rp => EF.Functions.Like(ppdd.d.DefendantCode, "%" + input.DefendantCode + "%"))
                      select ppdd;
}

if (input.ProductId != null) {
    ProdsProdDefDef = ProdsProdDefDef.Where(ppdd => ppdd.p.Id == input.ProductId);
}

if (input.ProductName != null && input.ProductId == null) {
    ProdsProdDefDef = ProdsProdDefDef.Where(ppdd => EF.Functions.Like(ppdd.p.ProductName, "%" + input.ProductName + "%"));
}

var productsVM = from ppdd in ProdsProdDefDef
                 select new GetProductsReturnViewModel {
                     Id = ppdd.p.Id,
                     ProductName = ppdd.p.ProductName,
                     DefendantCode = ppdd.d.DefendantCode
                 };

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-23
    • 1970-01-01
    • 2022-11-17
    • 2012-07-29
    • 1970-01-01
    • 1970-01-01
    • 2016-07-25
    相关资源
    最近更新 更多