2011-12-20 114 views
1

我想使用Levenshtein距离Linq选择查询(如下所示)它会引发异常。Linq to Entities:不认识的方法

IEnumerable<Host> closeNeighbours = (from h in _dbContext.People 
             let lD = Utilities.LevenshteinDistance(lastName, h.LastName) 
             let length = Math.Max(h.LastName.Length, LastName.Length) 
             let score = 1.0 - (double)lD/length 
             where score > fuzziness 

             select h); 



public static int LevenshteinDistance(string src, string dest) 
{ 
    int[,] d = new int[src.Length + 1, dest.Length + 1]; 
    int i, j, cost; 
    char[] str1 = src.ToCharArray(); 
    char[] str2 = dest.ToCharArray(); 

    for (i = 0; i <= str1.Length; i++) 
    { 
     d[i, 0] = i; 
    } 
    for (j = 0; j <= str2.Length; j++) 
    { 
     d[0, j] = j; 
    } 
    for (i = 1; i <= str1.Length; i++) 
    { 
     for (j = 1; j <= str2.Length; j++) 
     { 

      if (str1[i - 1] == str2[j - 1]) 
       cost = 0; 
      else 
       cost = 1; 

      d[i, j] = 
       Math.Min(
        d[i - 1, j] + 1,    // Deletion 
        Math.Min(
         d[i, j - 1] + 1,   // Insertion 
         d[i - 1, j - 1] + cost)); // Substitution 

      if ((i > 1) && (j > 1) && (str1[i - 1] == 
       str2[j - 2]) && (str1[i - 2] == str2[j - 1])) 
      { 
       d[i, j] = Math.Min(d[i, j], d[i - 2, j - 2] + cost); 
      } 
     } 
    } 

    return d[str1.Length, str2.Length]; 
} 

它似乎没有工作。任何选择?

例外: System.NotSupportedException是由用户代码未处理 消息= LINQ实体无法识别方法“的Int32编辑距离(System.String,System.String)”方法,和这种方法不能被翻译成存储表达。 Source = System.Data.Entity

回答

3

您不能在实体框架查询中使用该函数,因为EF无法将其转换为适当的TSQL。您必须将源序列放入内存中,允许在数据库中适用任何过滤器,然后在linq-to-objects中执行其余的过滤器。这只是一个微妙的变化。

var closeNeighbors = from h in db.People.AsEnumerable() // bring into memory 
        // query continued below as linq-to-objects 
        let lD = Utilities.LevenshteinDistance(lastName, h.LastName) 
        let length = Math.Max(h.LastName.Length, LastName.Length) 
        let score = 1.0 - (double)lD/length 
        where score > fuzziness 
        select h; 

AsEnumerable()之前的所有内容都会发生在数据库中。如果过滤器通常适用于People,则可以在调用AsEnumerable()之前使用这些过滤器。示例

var mixedQuery = db.People 
        .Where(dbPredicate).OrderBy(dbOrderSelector) // at the database 
        .AsEnumerable() // pulled into memory 
        .Where(memoryPredicate).OrderBy(memoryOrderSelector); 
+0

非常感谢。它确实有效。赞赏。 – 2011-12-20 05:46:11

相关问题