LINQ to Entities不能识别'System方法.String[]分裂(Char []) & # 39

本文关键字:分裂 Char String 方法 不能 Entities to 识别 System LINQ | 更新日期: 2023-09-27 18:05:37

我正试图实现一种方法,其中存储在数据库中的关键字用于活动(由逗号分割)匹配由逗号分割的给定字符串。

public List<TblActivities> SearchByMultipleKeyword(string keywords)
{
    string[] keyword = keywords.Split(',');
    var results  = (from a in Entities.TblActivities
                    where a.Keywords.Split(',').Any(p => keyword.Contains(p))
                    select a).ToList();
    return results;
}

我得到以下错误:

LINQ to Entities does not recognize the method 'System.String[] Split(Char[])' method,
and this method cannot be translated into a store expression.

LINQ to Entities不能识别'System方法.String[]分裂(Char []) & # 39

如错误信息所示,使用实体框架不能这样做。

但是,还是有选择的

一个选项是实现,如果关键字存储为A,B,C,D,则x在那里,如果

a.Keywords.StartsWith(x + ",") || 
a.Keywords.Contains("," + x + ",") || 
a.Keywords.EndsWith("," + x)

如果x本身不包含,,则有效。缺点是,这将对表或包含Keywords列的索引进行完全扫描。

另一种选择是规范化数据库。毕竟,活动和关键字之间是一对多的关系。然后这样建模:除了Activities表(没有Keywords列)之外,还有一个KeyWords表,它有两个列,一个活动表的外键和一个keyword列。这将允许您在keyword列上添加索引,这可以使查询超级快。

我重读了你的问题,并注意到你没有测试关键字相等,而只是Contains。如果是这样,为什么不这样做呢?

a.Keywords.Contains(x)

是的,你可以这样做:

public List<TblActivities> SearchByMultipleKeyword(string keywords)
{
    string[] keywordsSeparated = keywords.Split(',');
    var results  = (from a in Entities.TblActivities
                    where keywordsSeparated.Any(keyword => a.Keywords.Contains(keyword))
                    select a).ToList();
    return results;
}

实体框架不支持String.Split。这只是因为在SQL中没有相应的。

解决方案是:

  1. 在数据库中定义自定义函数本文提出了几种解决方案:http://sqlperformance.com/2012/07/t-sql-queries/split-strings
  2. 声明这个函数可以被LINQ使用[EdmFunction]属性的实体使用,就像这里解释的那样:如何从EF LINQ查询调用DB函数?

对于不涉及太多关键字和太多行的查询,您可以实现这个简单而快速的解决方案。您可以轻松地绕过Split函数,方法是重复修改结果,如下:

 public List<TblActivities> SearchByMultipleKeyword(string keywords)
 {
     string[] keywords = pKeywords.Split(',');
     var results = Entities.TblActivities.AsQueryable();    
     foreach(string k in keywords){
         results  = from a in results
                    where a.Keywords.Contains(k)
                    select a;
     }
     return results.ToList();
 }

LINQ to Entities尝试将您的LINQ查询转换为SQL。因为它不知道如何在SQL查询中执行String.Split,所以它失败了。

这意味着除非你想写一个String.Split的SQL实现,你只能在LINQ对象中做,这意味着你需要首先将所有的数据加载到内存中,然后执行where子句。一个简单的方法是使用.ToList():

var results  = (from a in Entities.TblActivities select a).ToList(); //Results are now in memory
results = results.Where(a =>
     a.Keywords.Split(',').Any(p => keyword.Contains(p))).ToList(); //This uses LINQ-to-objects

不确定,但可以试试:由于错误似乎是在寻找一个数组,这可能会起作用。

string[] keyword = keywords.Split(new char[] {','});
var results  = (from a in Entities.TblActivities
                where a.Keywords.Split(new char[] {','}).Any(p => keyword.Contains(p))
                select a).ToList();