【问题标题】:Entity, Contains or intersect, is this query possible?实体、包含或相交,这个查询可能吗?
【发布时间】:2016-09-28 20:38:19
【问题描述】:

我有一个这样检索的字符串列表:

List<string> keyWords = db.MotCleRecherche.Select(t => t.MotClé).ToList();

我还有一个需要执行许多参数的查询:

object = db.DAapp.Where(t => t.CODE_ART.StartsWith(s) && t.DATE_CREAT >= debut && t.DATE_CREAT < fin).ToList()

现在...我想添加这种条件:

  db.DAapp.Where(t => t.DESC_ART.ToLower().Contains(keywords.ToLower()))

  db.DAapp.Where(t => t.DESC_ART.ToLower().Intersect(keywords.ToLower()))

我猜你可能会看到它的到来......我不知道如何真正完成这项工作......我所知道的只是考虑一个 X 提交的列表和 Y 的列表填充:

X.Intersect(Y).Any()

如果有相等的东西,将返回真......但 DESC_ART 只是一个长字符串,我想知道我的一些关键字是否在那里

【问题讨论】:

  • 你可能可以这样做:db.DAapp.Where(t =&gt; keyWords.Contains(t.DESC_ART.ToLower()) ...你会想ToLower()你的整个关键字首先db.MotCleRechercher.Select(t =&gt; t.MotCle.ToLower()).ToList()
  • @stephen.vakil 关键字列表从一开始就放低是一件好事,谢谢,但是关键字不可能包含 desc_art,desc_art 就像 500 辆汽车一样长,而我的大多数关键字都有 5或 6 个字母...
  • 我明白了 - 您想搜索包含任何指定关键字的任何 DESC_ART 吗?所以像t =&gt; keyWords.Any(k =&gt; t.DESC_ART.Contains(k))
  • 我工作!!!太棒了!

标签: c# entity-framework


【解决方案1】:

我同意 Stephen 的观点,即您应该在比较之前先将关键字调低。但是如果你真的需要用 linq 来做这件事,你可以做这样的事情。

var result =  db.DAapp.Where(t => keywords.Any(keyword=> string.Equals(keyword,t.DESC_ART, StringComparison.InvariantCultureIgnoreCase )));

这将导致 a to lower 在您的 linq 循环的每次迭代中在每个字符串上被调用,因此它很昂贵。

【讨论】:

  • 当它到达数据库时会起作用吗?根据一些really old SO 答案,我认为它不会按预期工作。但也许 5 年内发生了一些变化? :)
  • 是的,我忘记了。不,它没有修复。只需获得对您的数据库的管理员访问权限并编辑表格!看,简单!
【解决方案2】:

首先将其添加到您的项目中(例如添加到您的控制器中):

      static Expression<Func<T, bool>> AnyOf<T>(
      params Expression<Func<T, bool>>[] expressions)
    {
        if (expressions == null || expressions.Length == 0) return x => false;
        if (expressions.Length == 1) return expressions[0];

        var body = expressions[0].Body;
        var param = expressions[0].Parameters.Single();
        for (int i = 1; i < expressions.Length; i++)
        {
            var expr = expressions[i];
            var swappedParam = new SwapVisitor(expr.Parameters.Single(), param)
                                .Visit(expr.Body);
            body = Expression.OrElse(body, swappedParam);
        }
        return Expression.Lambda<Func<T, bool>>(body, param);
    }
    class SwapVisitor : ExpressionVisitor
    {
        private readonly Expression from, to;
        public SwapVisitor(Expression from, Expression to)
        {
            this.from = from;
            this.to = to;
        }
        public override Expression Visit(Expression node)
        {
            return node == from ? to : base.Visit(node);
        }
    }

我从stackoverflow 找到这个。现在您可以创建所需的查询,如下所示:

        var filters = new List<Expression<Func<Models.DAapp, bool>>>();
        foreach (var st in keyWords)
            filters.Add(d => d.DESC_ART.ToLower().Contains(st.ToLower()));

        var lambda = AnyOf(filters.ToArray());

        var q = db.DAapp.Where(t =>
            t.CODE_ART.StartsWith(s)
            && t.DATE_CREAT >= debut
                && t.DATE_CREAT < fin
                           );

        q = q.Where(lambda);

        var res = q.ToList();

请注意,此解决方案仅创建一个带有多个 where 表达式的选择查询。这比像下面这样在 where 子句中包含多个选择查询的其他解决方案更有效:

var q = db.DAapp.Where(t =>
            t.CODE_ART.StartsWith(s)
            && t.DATE_CREAT >= debut
                && t.DATE_CREAT < fin
                && keyWords.Any(k => t.DESC_ART.ToLower().Contains(k.ToLower()))
                           );

【讨论】:

    猜你喜欢
    • 2011-05-16
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多