【问题标题】:Dynamic where clause in Linq to EntitiesLinq to Entities 中的动态 where 子句
【发布时间】:2012-02-25 16:35:30
【问题描述】:

我正在使用 linq 到实体 (EF)。 我有一个带有 4 个字符串参数的构造函数。根据什么参数不为空,我必须构建 linq 查询。我可以使用 if else 语句,但我还有其他带有 10 个参数的构造函数,在这种情况下将有很多组合需要检查。

例子:

Constructor(p1,p2,p3,p4)
{
  var prod= from p in ctxt.products.expand("items\details")
            where p.x==p1 && p.xx==p2 && p.xxx==p3 && p.xxxx==p4
            select p;
}

在上面的 where 子句中,只有当参数不为空时才应该进行条件检查。 IE。, 如果 p2 为空,那么 where 子句应该是这样的

where p.x==p1 && p.xxx==p3 && p.xxxx==p4

如果 p2 和 p3 为空,则

where p.x==p1 && p.xxxx==p4

谁能告诉我如何处理这个问题。如果可能的话,您可以为此提供示例代码

【问题讨论】:

标签: linq entity-framework dynamic where-clause


【解决方案1】:

您可以根据需要链接方法:

 YourType(string p1, string p2, string p3, string p4)
 {
      var prod = ctxt.Products.Expand("items\details");

      if (!p1.IsNullOrWhiteSpace())
          prod = prod.Where(p => p.x == p1);
      if (!p2.IsNullOrWhiteSpace())
          prod = prod.Where(p => p.xx == p2);

      // ....

      // use "prod"
 }

生成的 SQL 应该与将它们全部放在一个语句中一样。

【讨论】:

  • 如果我们这样做,我们将在 prod 中加载大量数据,然后我们将获取其中的子集。我们可以直接获取子集,否则我们正在加载不必要的数据
  • @Deepak 不,你不会。 IQueryable 的好处是它不会“加载数据”——LINQ 使用延迟执行,并且使用 EF,它将最终的“查询”转换为单个 SQL 语句。这将是相同的结果。
  • 这里 p1 和 p2 在 AND 条件下相加。有没有办法强制执行 OR 连接?
【解决方案2】:

Linq 的 DeferredExecution 来救援。除非向它请求数据,否则不会执行 Linq 查询。

var prod = from p in ctxt.products.expand("items\details")
        select p;

if (p1 != null)
{
    prod = prod.Where(p => p.x == p1);
}

if (p2 != null)
{
    prod = prod.Where(p => p.xx == p2);
}

// Execute the query

var prodResult = prod.ToList();

【讨论】:

  • 如果我们这样做,我们将在 prod 中加载大量数据,然后我们将获取其中的子集。我们可以直接得到子集吗?
  • 查询是执行的,直到 where 子句构建之后。在上面的代码中,查询一直构建到最后一行,这就是它执行的地方。您可以通过运行 SQL 分析器来检查这一点。
  • 是的,你是对的。我可以使用你的代码并且它可以完美运行。
  • 我们可以在这里使用异步吗?
  • 这里 p1 和 p2 在 AND 条件下相加。有没有办法强制执行 OR 连接?
【解决方案3】:

您始终可以分段构建查询并利用延迟查询执行:

public Constructor(int? p1, int? p2, int? p3, int? p4)
{
    var prod = ctxt.products.expand("items\details");

    if(p1 != null)
        prod = prod.Where(p.x == p1);

    if(p2 != null)
        prod = prod.Where(p.xx == p2);

    if(p3 != null)
        prod = prod.Where(p.xxx == p3);

    if(p4 != null)
        prod = prod.Where(p.xxxx == p4);
}

【讨论】:

  • 如果我们这样做,我们将在 prod 中加载大量数据,然后我们将获取其中的子集。我们可以直接获取子集,否则我们正在加载不必要的数据
  • @Deepak - 您根本不会加载任何数据。在您实际使用数据之前,LINQ 不会执行查询。到查询执行时,您已经有了适当的 where 子句来仅加载您需要的数据。
  • 这里 p1 和 p2 在 AND 条件下相加。有没有办法强制执行 OR 连接?
猜你喜欢
  • 2013-01-15
  • 1970-01-01
  • 2011-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-21
  • 2011-11-25
相关资源
最近更新 更多