C# LINQ to实体无法识别方法“System.String[]Split(Char[])”方法,

C# LINQ to实体无法识别方法“System.String[]Split(Char[])”方法,,c#,string,linq,C#,String,Linq,我试图实现一种方法,其中存储在数据库中的活动关键字以逗号分隔,与给定字符串以逗号分隔相匹配 public List<TblActivities> SearchByMultipleKeyword(string keywords) { string[] keyword = keywords.Split(','); var results = (from a in Entities.TblActivities where a.Key

我试图实现一种方法,其中存储在数据库中的活动关键字以逗号分隔,与给定字符串以逗号分隔相匹配

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实体尝试将LINQ查询转换为SQL。因为它不知道如何在SQL查询中执行String.Split,所以它失败了

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


正如错误消息所说,您不能使用实体框架来实现这一点

但是,也有选择

一种选择是认识到,如果关键字存储为A、B、C、D,那么如果

a.Keywords.StartsWith(x + ",") || 
a.Keywords.Contains("," + x + ",") || 
a.Keywords.EndsWith("," + x)
如果x本身不包含,则该方法有效。缺点是,这将对表或包含关键字列的索引进行完整扫描

另一个选项是规范化数据库。毕竟,活动和关键字之间有一对多的关系。然后对其进行建模:除了没有关键字列的活动表之外,还有一个包含两列的关键字表、活动表的外键和关键字列。这将允许您在关键字列上添加一个索引,这可以使查询超快速

更新

我重读了你的问题,注意到你不是在测试关键字是否相等,而是在测试包含。如果是这样的话,你为什么不做下面的事情呢

a.Keywords.Contains(x)
不确定,但您可以尝试: 由于错误似乎是在查找数组,因此这可能会起作用

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();
实体框架不支持String.Split。这仅仅是因为在SQL中没有等价物

解决办法是:

在数据库中定义自定义函数的步骤 本文提出了几种解决方案: 要声明此函数可由LINQ使用[EdmFunction]属性对实体使用,如下所述:
对于不涉及太多关键字和太多行的查询,您可以实现这个简单而快速的解决方案。通过反复优化结果,您可以轻松绕过拆分函数,如下所示:

 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();
 }

是的,你可以这样做:

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;
}

错误表明您无法使用这些函数,因为它们不可用。这些函数与TSQL之间没有映射。更好的选择可能是使用context.ExecuteStoreQuery,您可以在其中自己编写SQL。您是否查看了右侧的相关问题?粗略地看一眼,你会很快找到答案…@3dd完全不同意你的观点。正确的选择是实际规范化数据库,以便实际使用SQL、索引和表统计信息。否则,使用RDBMS的意义何在。如果您真的想这样做CSV gubbins,请改用无模式数据库@Aron不一定是真的,我们不知道关键字列的上下文,它可能不可规范化,但我同意,如果它被规范化,它会更好。如果我们最多谈论兆字节,这可能会起作用,尽管它可能非常慢。如果我们谈论的是千兆字节,它甚至可能不起作用。@KrisVandermotten我同意。可能正确的解决方案是更改数据库或编写自定义SQL,但这两种方法中的任何一种似乎都超出了问题的范围。如果EF/Linq to Entities能够支持String.Split,那就太好了。我同意所选的第一个选项。您忘记了只有一个存储库的情况。添加:a.Keywords.StartsWithx | |我认为您的代码示例中有一个输入错误。它应该是SearchByMultipleKeywordstring pKeywords-注意pKeywords而不是简单的关键字。我不知道为什么这一点没有被提升-这是唯一正确和可信的答案。我必须同意@JohnOhara。这对我来说非常有效。我使用了它,并将结果与我试图在SSMS中实现的SQL脚本进行了比较。
 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();
 }
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;
}