【问题标题】:Search query gives LINQ to SQL exception搜索查询给出 LINQ to SQL 异常
【发布时间】:2011-10-10 22:56:45
【问题描述】:

对于以下查询,我得到一个 LINQ to SQL 异常。

var terms = "bob town".Split(' ');
var q = from m in db.Monument
    where terms.All(t => new List<string>() {
        m.Name,
        m.Street,
        m.Owner }.Any(
            p => p.Contains(t)))
    select m;

例外是:

在查询的 LINQ to SQL 实现中不能使用本地序列 除包含运算符之外的运算符。

如何修改查询以与 LINQ to SQL 兼容?


目标

查询的目标是这样的。我有一个搜索词列表和一个包含对象的数据库。如果所有搜索词都是至少一个属性的子字符串,则应返回一个对象。

例如。如果有一个对象oo.name="creek mill"o.street="St. Petersroad",则搜索“mill petersroad”应返回此对象,但搜索“mill foobar”不应返回。

【问题讨论】:

标签: c# linq linq-to-sql exception contains


【解决方案1】:

所以,实际的问题是 Linq-To-SQL 不知道如何将 Linq 的 Terms 部分转换为有效的 SQL 语句。因此,您必须重新调整查询以帮助解决问题。

我假设我们想使用Contains 函数来获取使用SQL IN 运算符的SQL 语句。这是我的建议。

var terms = "bob town".Split(' ');
var q = from m in db.Monument
    where 
            terms.Contains(m.Name)
        ||
            terms.Contains(m.Street)
        ||
            terms.Contains(m.Owner)
    select m;

我没有对此进行测试,但它看起来应该可以工作并且应该由 Linq-To-SQL 转换。

【讨论】:

    【解决方案2】:

    下面呢。我还没有尝试过,但它给了你一个想法

    var terms = "bob town".Split(' ');
            var q = from m in db.Monument
                    where m.Name.Split(' ').Intersect(terms).Count() > 0 ||
                            m.Street.Split(' ').Intersect(terms).Count() > 0
                    select m; 
    

    无论如何,我认为对于这种搜索,如果你有一个非常适合你的上下文的 SQL db 或“.net lucene”,你应该考虑使用 SQL 全文搜索

    【讨论】:

    • 我们不想要精确的文本匹配,例如搜索“Petersroad”应该匹配“St. Petersroad”。此外,所有搜索词必须至少匹配一次。您可能说得对,它在 LINQ 中不可行。
    • 我已经编辑了我的答案,它现在应该可以工作了。 “相交”将返回两个序列的任何交集:-)
    • 我不确定这是否正是他想要的。这将返回包含词条的实体,但不返回包含所有个搜索词条的实体。
    • 我已经编辑过了。这只是一种方法。他们的关键是使用“相交”功能
    【解决方案3】:

    我确信可能有一种方法可以使用纯 LINQ 来做到这一点,但我不太确定这是否真的是一个好主意:恕我直言,人们有时倾向于过度烹饪他们的 LINQ 查询而不是特别除了LINQ 非常酷之外的其他原因,最终得到的查询非常仅通过查看它们就难以理解。

    您为什么不实现一个扩展方法,该方法采用Monument 实体并确定某个string[] 是否符合您的条件?

    这样你的LINQ 表达式再简单不过了:

    var q = from m in db.Monument
    where m.ContainsAllSearchTerms(terms)
    select m; //readable and anyone understands right away what is going on here
    

    作为ContainsAllSearchTerms(this Monument m, string[] terms)相关的扩展方法。

    【讨论】:

    • 你的建议可读性很强,但还是会转成SQL?在 C# 中循环遍历所有实体可能太慢了。
    • 我不确定这是否可以避免,无论你怎么做。也许您应该研究一下 Massimiliano 提到的所有不同选项(SQL 全文搜索等)。我的建议是尝试类似于我建议的方法,如果性能很糟糕,那么可能会检查其他方法。但我的建议是始终先检查最简单的路径。过早的优化通常是个坏主意。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-17
    • 1970-01-01
    相关资源
    最近更新 更多