【问题标题】:Repeat 'where' clause on EF在 EF 上重复“where”子句
【发布时间】:2014-07-14 08:34:07
【问题描述】:

如何使 EF 'where' 子句重复类似的内容:

var query = from p in db.Posts
            where p.Title == "title" && p.Author == "author"
            where p.Title == "title" && p.Author == "author"

            select p;

现在标题和作者当然来自 List 对象,类似于:

List<string> authors = new List<string>(){ "author1", "author2", "author3" }
List<string> titles = new List<string>(){ "title1", "title2", title3" }

我可以在这里使用包含,但要求是相应地匹配标题和作者。由于作者和标题是参数,我不能只对它们进行硬编码并进行简单查询

示例 SQL 查询将是:

select * 
from Posts
where (title = "title1" AND author = "author1") OR
      (title = "title2" AND author = "author2") OR
      (title = "title3" AND author = "author3")

【问题讨论】:

  • 您到底想得到什么作为查询结果?
  • 你的意思是where p.Title == "X" &amp;&amp; p.Author == "Y" || p.Title == "P" &amp;&amp; p.Author == "Q"
  • 你的问题一点都不清楚。您能否进一步解释一下您真正追求的是什么?以上内容似乎与实体框架无关。
  • 我猜你需要使用“或”,即 ||而不是你第二次使用'where',虽然这会导致一些废话。
  • 已编辑:添加了预期的 sql 查询。顺便说一句,我正在使用 EF,所以如果这在 Linq-to-SQL 上可以正常工作,我很乐意删除 EF 的标签

标签: c# linq lambda entity-framework-6.1


【解决方案1】:

我假设您实际上想要标题和作者之间的 &&,但是 ||在每个标题/作者组合之间。假设你有这些:

Expression<Func<Post, bool>> where1 = p => p.Title == "title1" && p.Author == "author1";
Expression<Func<Post, bool>> where2 = p => p.Title == "title2" && p.Author == "author2";

如果您创建以下扩展方法:

    /// <summary>
    /// Combines two lambda expressions into a single expression.
    /// In the returned expression, the parameter in the second expression will be replaced
    /// with the parameter from the first.
    /// </summary>
    /// <param name="source">The first expression to combine.</param>
    /// <param name="other">The second expression to combine.</param>
    /// <param name="combiner">
    /// How to combine the expression bodies.
    /// Example: <see cref="Expression.Or(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)"/>
    /// </param>
    /// <returns></returns>
    public static Expression<Func<T1, T2>> Combine<T1, T2>(
        this Expression<Func<T1, T2>> source,
        Expression<Func<T1, T2>> other,
        Func<Expression, Expression, BinaryExpression> combiner)
    {
        var sourceParam = source.Parameters[0];
        var visitor = new ParameterReplacerVisitor(other.Parameters[0], sourceParam);
        var visitedOther = visitor.VisitAndConvert(other, "Combine");
        Require.That(visitedOther != null, () => "VisitAndConvert failed to return a value.");
        var newBody = combiner(source.Body, visitedOther.Body);
        return Expression.Lambda<Func<T1, T2>>(newBody, sourceParam);
    }

...它使用以下ParameterReplacerVisitor 类:

/// <summary>
/// This class replaces one parameter with another everywhere in a given expression tree.
/// This is handy when you have two lambda expressions that you want to combine into one.
/// </summary>
public class ParameterReplacerVisitor : System.Linq.Expressions.ExpressionVisitor
{
    private readonly ParameterExpression _originalParameter;
    private readonly ParameterExpression _newParameter;

    public ParameterReplacerVisitor(ParameterExpression originalParameter, ParameterExpression newParameter)
    {
        _originalParameter = originalParameter;
        _newParameter = newParameter;
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        if (node == _originalParameter)
        {
            node = _newParameter;
        }
        return base.VisitParameter(node);
    }
}

...那么你可以像这样组合这些表达式:

var either = where1.Combine(where2, Expression.Or);

然后你可以说:

var query = db.Posts.Where(either);

【讨论】:

  • hmm,我会尝试这个,但我相信会生成使用子查询而不是“where”子句上的 OR 的 sql。您能否告诉我您对上述谓词的预期查询是什么?
  • @gnaungayan:为什么会产生子查询?它正在创建一个等效于 p =&gt; (p.Title == "title1" &amp;&amp; p.Author == "author1") || p.Title == "title2" &amp;&amp; p.Author == "author2") 的表达式。
【解决方案2】:

您的要求的第一印象是您可能需要执行.Contains 以从数据库中提取记录,然后查看使用Dynamic Linq 从您的参数中进一步过滤。

【讨论】:

    猜你喜欢
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    • 2018-07-19
    • 1970-01-01
    • 2021-09-29
    • 2019-02-06
    • 2012-06-08
    • 2013-08-11
    相关资源
    最近更新 更多