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