6

我有以下 LINQ 查询:

var aKeyword = "ACT";
var results = from a in db.Activities
              where a.Keywords.Split(',').Contains(aKeyword) == true
              select a;

关键字是逗号分隔的字段。

每次运行此查询时,我都会收到以下错误:

“LINQ to Entities 无法识别方法 'Boolean Contains[String](System.Collections.Generic.IEnumerable`1[System.String], System.String)' 方法,并且此方法无法转换为存储表达式。”

我想做的事情的替代方法是什么?

4

4 回答 4

8

您的问题是 LINQ-to-Entites 必须将您提供的所有内容转换为 SQL 以发送到数据库。

如果这确实是您需要做的,您将不得不强制 LINQ-to-Entities 拉回所有数据和 LINQ-to-Objects 以评估条件。

前任:

var aKeyword = "ACT";
var results = from a in db.Activities.ToList()
              where a.Keywords.Split(',').Contains(aKeyword) == true
              select a;

但请注意,这将拉回活动表中的所有对象。另一种方法可能是让数据库做一些初始过滤,然后过滤剩下的部分:

var aKeyword = "ACT";
var results = (from a in db.Activities
              where a.Keywords.Contains(aKeyword)
              select a).ToList().Where(a => a.KeyWords.Split(',').Contains(aKeyword));

这将让 LINQ-to-Entities 执行它所理解的过滤器(string.Contains 成为类似查询),该过滤器将过滤掉一些数据,然后在您获得对象后通过 LINQ-to-Objects 应用您想要的真实过滤器. ToList() 调用强制 LINQ-to-Entities 运行查询并构建对象,从而允许 LINQ-to-Objects 成为执行查询第二部分的引擎。

于 2009-08-30T19:45:20.613 回答
6

针对您对大型数据集的性能考虑:

您将在客户端上进行非索引通配符字符串匹配,所以是的,会有性能损失。

一个表字段中有多个关键字是有原因的吗?您可以将其标准化,以获得一个 ActivityKeywords 表,其中对于每个 Activity,您都有许多关键字记录。

活动(activity_id, ... /* 删除关键字字段 */) ---> ActivityKeywords(activity_id, keyword_id) ---> 关键字(keyword_id, value)

查看非第一范式:http ://en.wikipedia.org/wiki/Database_normalization

编辑:此外,即使您坚持使用一列,也有一种方法可以在服务器端执行所有操作(如果您有严格的语法:'keyword1,keyword2,...,keywordN'):

var aKeyword = "ACT";
var results = (from a in db.Activities
              where a.Keywords.Contains("," + aKeyword) || a.Keywords.Contains(aKeyword + ",")
              select a;
于 2009-08-30T20:35:30.137 回答
0

我的猜测是您调用拆分的方式。它应该需要一个数组。也许在 Linq 中存在另一个拆分,它正在发现并给您一个不寻常的错误:

这适用于 Linq to Objects:

 var dataStore = new List<string>
                    {
                        "foo,bar,zoo",
                        "yelp,foo",
                        "fred",
                        ""
                    };
 var results = from a in dataStore
               where a.Split(new[] {','}).Contains("foo")
               select a;

 foreach (var result in results)
 {
     Console.WriteLine("Match: {0}", result);
 }

输出以下内容:

Match: foo,bar,zoo
Match: yelp,foo

其实想一想,你还需要分裂吗? a.Contains("foo")对你来说可能就足够了(除非你不想打foobar)。

于 2009-08-30T19:48:22.447 回答
0

您可能想查看有关 L2E 和 .Contains的这个问题,以寻求比在过滤客户端之前猜测超集更有效的解决方案。

于 2009-08-30T20:12:49.637 回答