【问题标题】:Unable to use certain functions with LINQ to Entities?无法将某些功能与 LINQ to Entities 一起使用?
【发布时间】:2015-02-27 15:33:47
【问题描述】:

我正在尝试使用 LINQ 查询在项目中实现搜索功能。因为数据有时包含带有重音符号和其他符号的字符,所以我创建了一种方法来删除这些以进行搜索。

这是我的代码:

var addresses = (from a in db.Addresses
                 join b in db.Addresses on a.ClientID equals b.ClientID
                 where a.AddressType == 1 && b.AddressType == 2
                 select new
                 {
                     /* Columns selected */
                 });
var q = (from e in db.Employers
         join a in addresses on e.EmployerID equals a.id
         join i in db.IndustrialSectors on e.IndustrialSector equals i.ID
         select new
         {
             /* Columns selected */
         });

if (search != "")
{
    q = (from i in q
         where (
           Util.StringUtil.RemoveDiacritics(i.entity.ToString().ToLowerInvariant()).Contains(search) ||
           Util.StringUtil.RemoveDiacritics(i.name.ToString().ToLowerInvariant()).Contains(search)
         )
         select i);
}

它会生成一个异常,指出 LINQ to Entities 无法识别我的方法 (RemoveDiacritics(String))。

【问题讨论】:

  • LINQ to entity 将尝试将您的 LINQ 表达式转换为 SQL 或基础数据源语言。由于您的 particular 方法没有任何表示,因此它会引发异常。
  • 如果您的底层数据源语言是 SQL,您可以在 Entity Framework Linq 查询中使用 SqlFunctions 类中的静态方法
  • 您针对哪种 SQL 方言进行编码?如果是 MS SQL Server,您能否将 RemoveDiacritics 函数实现为自定义函数,无论是在 T-SQL 中还是作为基于 CLR 的函数?

标签: c# linq entity-framework


【解决方案1】:

当您使用 LINQ-to-Entities 时,您的 LINQ 查询需要被翻译成“服务器端表达式”,这在英文中是指数据库可以执行的东西。数据库对名为 RemoveDiacritics 的 C# 方法一无所知,因此在运行时会出现错误。

您需要先执行查询,然后使用 LINQ-to-Objects 进行过滤。这可以通过在过滤之前向查询添加ToList() 来完成。我对流利的语法比较熟悉,所以我会写成:

q.ToList().Where(i =>
    Util.StringUtil.RemoveDiacritics(i.entity.ToString().ToLowerInvariant()).Contains(search) ||
    Util.StringUtil.RemoveDiacritics(i.name.ToString().ToLowerInvariant()).Contains(search));

如果你想要查询语法,你将不得不弄乱它。可能类似于以下内容,但我不能 100% 确定。

(from i in q.ToList()
 where Util.StringUtil.RemoveDiacritics(i.entity.ToString().ToLowerInvariant()).Contains(search) ||
       Util.StringUtil.RemoveDiacritics(i.name.ToString().ToLowerInvariant()).Contains(search));

但是请注意,这将从服务器返回所有内容,然后执行过滤客户端,这可能会导致系统出现性能问题,具体取决于表中包含的信息量.

【讨论】:

  • 你不希望“q”后面的括号:(from i in q).ToList()应该是(from i in q.ToList()
  • 我之前尝试在 if 块之前的查询上执行此操作,但我收到一个错误,它无法从 IEnumerable 隐式转换为 IQueryable。我认为这与我在搜索之前加入两个查询这一事实有关,因为我已经能够做到这一点。
  • @Steven Rands:已更正。就像我说的,我很少使用那种语法。
  • @MGKarlo,您是否尝试过我的建议或只是在其他地方尝试过类似的方法? q.ToList().Where()q.Where().ToList() 之间的结果应该没有任何不同。
  • 我设法通过使用 ToList().Select(o => new { /* columns */});回到第一个查询中,同时将两个查询合并为一个。不过,我仍然认为必须有更好的方法来实现这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
  • 2013-11-04
  • 1970-01-01
相关资源
最近更新 更多