2011-07-22 43 views
4

对于下面的查询,我得到一个LINQ to SQL异常。搜索查询给出了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被用来查询 运营商除了包含运营商的SQL实现。

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


目标

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

例如。如果oo.name="creek mill"o.street="St. Petersroad",那么搜索“mill petersroad”应该返回这个对象,但不应该搜索“mill foobar”。

+0

尝试杰森的答案。 HTTP://计算器。com/questions/194930/how-do-i-use-linq-containsstring-instead-of-containsstring/195628#195628会不会解决你的问题? – naveen

+1

您可能在http://blog.wekeroad.com/2008/02/27/creating-in-queries-with-linq-to-sql有一些运气 –

回答

0

下面是怎么回事。我还没有尝试过,但它给你一个想法约

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全文搜索,如果你有一个SQL数据库搜索或” .NET的Lucene “这真的很适合你的情况下

+0

我们不想要精确的文本匹配,例如搜索“Petersroad”应该匹配“St. Petersroad”。此外,所有搜索字词必须至少匹配一次。你可能会说这在LINQ中不可行。 – Matt

+0

我编辑了我的答案,它现在应该工作。 “相交”将返回两个序列的任何交集:-) –

+0

我不确定这正是他想要的。这将返回包含条款的实体,但不包含包含* all *搜索条件的实体。 – InBetween

0

我敢肯定,可能有一种方法可以做到这一点与纯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)相关的扩展方法。

+0

你的建议是非常可读的,但它仍然会被转换为SQL?循环遍历C#中的所有实体可能会太慢。 – Matt

+0

我不确定这是否可以避免,无论你如何做。也许你应该看看Massimiliano提到的所有不同的选项(SQL全文搜索等)。我的建议是尝试类似于我的建议,如果性能很差,那么也许检查其他方法。但我的建议是始终首先检查最简单的路径。不成熟的优化通常是一个坏主意。 – InBetween

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进行转换。