将带有COALESCE的SQL WHERE转换为LINQ

时间:2017-04-28 16:17:33

标签: c# linq

我正在尝试在控制器中生成一个过滤列表以传递给MVC视图。

我知道我可以在SQL中执行此操作:(我在某种程度上缩短了SQL ...)

SELECT ItemID, Item, SupplierID, Supplier, BrandID, Brand, CategoryID, Category, SubCategoryID, SubCategory, TypeID, Type
FROM Table1 join Table 2... etc

WHERE   (supplierid = @SID OR @SID = -99)   AND
    (brandid = @BID OR @BID = -99) AND
    (categoryid = @CID OR @CID = -99) AND ....

但是我想知道用C#和它做的最佳方法。 Linq(或者如果最好根据上面的内容调用存储过程并使用它)

这是我的控制器的开始:

public async Task<ActionResult> Index(int? supplierid, int? itembrandid, int? categoryid, int? subcategoryid, int? itemtypeid)
{
    List<DTOClasses.ItemsListDTO> items = new List<DTOClasses.ItemsListDTO>();

    items = await (from i in db.Items  
                   join b in db.ItemBrand on i.BrandID equals b.BrandID
                   join s in db.Suppliers on b.SupplierID equals s.SupplierID
                   join sc in db.SubCategories on i.SubCategoryID equals sc.SubCategoryID
                   join c in db.Categories on sc.CategoryID equals c.CategoryID                  
                   where // get stuck at this point
                   select new DTOClasses.ItemsListDTO
                   {
                       ItemId = i.ItemID
                       //etc..
                   }
                   ).ToListAsync();

    return View(items);
}

我希望尽可能避免编写可能的25个嵌套if语句。

**编辑

例如,为了保持linq查询干净整洁,让输入参数的每个组合与他们自己的查询一起执行。

    if( BID != null && SID != null && CID != null)
{ query 1}
else 
if (BID != null && SID != null && CID == null)
{query 2}

1 个答案:

答案 0 :(得分:0)

使用空合并运算符??,C#与COALESCE相当,但我不确定这与您的问题有何关联。 C#还具有与AND和OR在一起的多个条件的完全等价,所以就像SQL一样:

items = await (from i in db.Items  
               join b in db.ItemBrand on i.BrandID equals b.BrandID
               join s in db.Suppliers on b.SupplierID equals s.SupplierID
               join sc in db.SubCategories on i.SubCategoryID equals sc.SubCategoryID
               join c in db.Categories on sc.CategoryID equals c.CategoryID                  
               where ((b.BrandID == BID || BID == -99) &&
                      (s.SupplierID == SID || SID == -99) &&
                      (sc.CategoryID == CID || CID == -99))
               select new DTOClasses.ItemsListDTO
               {
                   ItemId = i.ItemID
                   //etc..
               }
               ).ToListAsync();

如果重复性对你的影响和我一样多,你可以将其隐藏在辅助扩展方法中,但是假设所有ID类型的幻数保持相同-99(并且忽略了使用幻数的错误程度)实际上是)。

static class IDExt {
    static bool IDMatches(this int anID, int testID) => testID == anID || testID == -99;
}

然后你有

where b.BrandID.IDMatches(BID) && s.SupplierID.IDMatches(SID) && sc.CategoryID.IDMatches(SID)