C# 根据条件将查询追加到何处

C# 根据条件将查询追加到何处,c#,entity-framework,C#,Entity Framework,我有这样一个问题: if (catId == null || catId == 0) { productVM = db.Products .Include(x => x.Category) .ToArray() .Select(x => new ProductVM(x)) .ToList(); } else { product

我有这样一个问题:

if (catId == null || catId == 0)
{
    productVM = db.Products
                  .Include(x => x.Category)
                  .ToArray()
                  .Select(x => new ProductVM(x))
                  .ToList();
}
else
{
    productVM = db.Products
                  .Include(x => x.Category)
                  .ToArray()
                  .Where(x => x.CategoryId == catId)
                  .Select(x => new ProductVM(x))
                  .ToList();
}
这是可行的,但正如您所看到的,这两个查询之间的唯一区别是
,其中(x=>x.CategoryId==catId)


有没有一种更优雅的方式来编写此命令?

只需重新分配查询:

var query = db.Products;

if (condition)
    query = query.Where(criteria);

var list = query.ToList();
另一种方式

var products = db.Products.Include(x => x.Category).ToArray()

if (catId == null || catId == 0)
{
    productVM = products.Select(x => new ProductVM(x)).ToList();
}
else
{
    productVM = products.Where(x => x.CategoryId == catId)
                        .Select(x => new ProductVM(x)).ToList();
}

实体框架实际上不会查询数据库,直到您将数据具体化,例如使用
ToList()
或迭代结果。因此,您可以在运行时构建查询,而无需访问数据库:

var query = db.Products.Include(x => x.Category);

if(catId != null && catId != 0)
{
    //Add a where clause
    query = query.Where(x => x.CategoryId == catId);
}

productVM = query
    .ToList()
    .Select(x => new ProductVM(x));

请注意,我删除了
ToArray
调用,因为这也使数据具体化,这意味着数据上的每个后续方法都作用于数据库中的整个表。

您可以扩展Where语句,以包括catId上的null或0测试。如果数据库中的字段catId可为空或值为0,则此操作可能不起作用

productVM = db.Products
    .Include(x => x.Category)
    .Where(x => catId == null || catId == 0 || x.CategoryId == catId)
    .Select(x => new ProductVM(x))
    .ToList();

您还应该删除ToArray()因为它从数据库查询整个Products表,然后在客户端的内存中执行过滤和投影。

这可能是个坏主意,因为它将
catId
检查传递到数据库。在我们的团队中,当条件转为简单类型时,我们在SQL/Linq查询中广泛使用这个概念,“而且效果很好。@DavidG-将条件传递给数据库服务器更为理想,因为这意味着无论catId的值如何,都将在服务器上创建和使用单个执行计划。实际上,这是完全错误的。”。将其传递给服务器意味着您正在传递服务器实际不需要的参数,并且查询计划仅针对catId为null或不为null的情况进行优化。最好有两个查询计划,每种情况一个。这看起来不错,但我得到一条红线,表示基本上
无法将IQueryable转换为List
,并且
productVM
声明如下:
List productVM我想我需要某种类型的强制转换,但不确定正确的方式?是否缺少结尾的
ToList
?错误是:无法隐式将类型“System.Collections.Generic.IEnumerable”转换为“System.Collections.Generic.List”。存在显式转换(是否缺少转换?)红线显示在
db.Products.Include(x=>x.Category)下
query.Where(x=>x.CategoryId==catId)哎呀,我刚才看到了一个复制/粘贴错误!再试一次