2010-07-18 35 views
1

我有这个在我的查询:方法 '包含布尔..' 有没有支持转换为SQL

var results = (from urls in _context.Urls 
       join documents in _context.Documents on urls.UrlId equals documents.DocumentId 
       let words = (from words in _context.Words 
          join hits in _context.Hits on words.WordId equals hits.WordId 
          where hits.DocumentId == documents.DocumentId 
          select words.Text).AsEnumerable<string>() 

       where urls.ResolvedPath.Contains(breakedQuery, KeywordParts.Url, part) || 
         documents.Title.Contains(breakedQuery, KeywordParts.Title, part) || 
         documents.Keywords.Contains(breakedQuery, KeywordParts.Keywords, part) || 
         documents.Description.Contains(breakedQuery, KeywordParts.Description, part) || 
         words.Contains(breakedQuery, KeywordParts.Content, part) ... 

,并包含扩展方法:

字符串

public static bool Contains(this string source, IEnumerable<string> values, KeywordParts valuePart, KeywordParts part) 
    { 
     if (!string.IsNullOrWhiteSpace(source)) 
      return source.Split(' ').AsEnumerable<string>().Contains(values, valuePart, part); 
     return false; 
    } 

枚举的(主要方法)

public static bool Contains(this IEnumerable<string> source, IEnumerable<string> values, KeywordParts valuePart, KeywordParts part) 
    { 
     if (source != null && source.Count() > 0 && 
      values != null && values.Count() > 0 && 
      (part == KeywordParts.Anywhere || valuePart == part)) 
     { 
      foreach (var value in values) 
      { 
       var has = false; 
       var none = (value.StartsWith("-")); 
       string term = value.Replace("-", ""); 

       if (none) 
        has = source.Any(q => !q.Contains(value)); 
       else 
        has = source.Any(q => q.Contains(values)); 

       if (has) 
        return has; 
      } 
     } 
     return false; 
    } 

并使用Contains方法抛出异常NotSupportedException:方法的布尔Contains(String,IEnumerable`1 [String],KeywordParts,KeywordParts)'没有支持的SQL转换。

其实我想,如果有在租赁的指定条件

回答

3

你不能只写你自己的方法,并从您的查询表达式打电话给他们一个检查每个索引文件 - 查询翻译根本不知道那是什么方法的意思是做。

你可能会迫使where子句在.NET获取的文件,也就是说,潜在的......虽然很明显,这意味着获取所有从数据库中加入数据后执行。那会好吗?

要做到这一点,你想要的东西,如:

var tmpQuery = (from urls in _context.Urls 
       join documents in _context.Documents 
       on urls.UrlId equals documents.DocumentId 
       let words = (from words in _context.Words 
          join hits in _context.Hits 
          on words.WordId equals hits.WordId 
          where hits.DocumentId == documents.DocumentId 
          select words.Text) 
       select new { urls, documents, words }; 

var query = from r in tmpQuery.AsEnumerable() 
      let urls = r.urls.ToList() 
      let words = r.words.ToList() 
      let documents = r.documents.ToList() 
      where urls.ResolvedPath.Contains(breakedQuery, 
              KeywordParts.Url, part) || 
       documents.Title.Contains(breakedQuery, 
             KeywordParts.Title, part) || 
       documents.Keywords.Contains(breakedQuery, 
              KeywordParts.Keywords, part) || 
       documents.Description.Contains(breakedQuery, 
               KeywordParts.Description, part) || 
       words.Contains(breakedQuery, KeywordParts.Content, part) 
      select new { urls, words, documents }; 
+0

非常好,谢谢你。你能给我一个方法来提高执行这个查询的速度吗?因为你知道我正在开发非常基本的网络搜索引擎,这是项目搜索部分的一部分。我检索结果后,我想排序结果按选择每个计算的速度。我将在单独问题中发布费率部分。 – Sadegh 2010-07-18 08:34:22

+0

这里是我的问题http://stackoverflow.com/questions/3274897/simple-rating-algohritm-to-sorting-results-according-to-user-query – Sadegh 2010-07-18 08:58:53

3

我的理解,有人请纠正我,如果我错了,问题是使用LINQ的扩展方法时到SQL扩展方法不像.NET代码那样执行,就像您在问题中使用的扩展方法一样。

Linq to SQL扩展方法返回expression trees,Linq to SQL引擎然后解析并生成适当的SQL查询以满足表达式树。

+0

是的,确切地说。在这种情况下,表达式树会引用对'Contains'的调用,这是LINQ to SQL不知道的。 – 2010-07-18 07:40:19

+0

@Jon,感谢您的确认。 – 2010-07-18 07:53:02

3

实现此功能的另一种方法是在实现此功能的数据库中编写标量UDF。然后将该UDF拖放到LINQ-to-SQL设计器上,该设计器将允许您通过数据上下文访问UDF。然后你可以使用的东西,如:

where _context.MyContains(documents.Title, breakedQuery, 
     KeywordParts.Title, part); 

和翻译之后,将调用UDF(即WHERE dbo.MyContains(...)

1

这个一个有趣的事实是,我在运行.NET 4.0时,遇到下列错误我开发机器:

“Method'Boolean Contains(Int32)'has no supported translation to SQL。”

但是它在使用.NET 3.5的生产环境中运行得很好。

我猜测这是两种环境之间版本的差异。然而,这是一个事实,我得到我的开发机器上的错误,但这些查询运行的生产环境和LINQ查询确实包含下面的代码

var resultParts = (
       from l in tempDc.LineItems 
       from wo in tempDc.WorkOrders 
       where l.WorkOrderNumber == wo.WorkOrderNumber && 
        l.OrderID == wo.OrderID && 
        workOrderSerialNumbers.Contains(wo.SerialNumber) && 
        l.Part.PartTypeID == (int)PartTypes.InventoryPart 
       orderby l.OrderID_WO, l.WorkOrderNumber 
       select new PickReportPartDto() 
       {... 

哪里workOrderSerialNumbers是一个列表。

0

这是可能的,如果你把你的枚举并添加到.ToList()之前.Contains(r.SomeId)。我正在寻找这个错误,最初有一个ICollection与.Contains(r.SomeId)会抛出这个异常,但是做一个.ToList()解决了我的问题。希望这可以帮助别人。

注:我相信有一个表达式树最大Linq2Sql ...所以一个大的列表可能会导致你另一个头痛。只是一个想法和需要注意的事情。

这是LINQ2SQL代码:

enter image description here

这是导致SQL: enter image description here

相关问题