LINQ to Entities 无法识别该方法

Posted

技术标签:

【中文标题】LINQ to Entities 无法识别该方法【英文标题】:LINQ to Entities does not recognize the method 【发布时间】:2011-11-07 17:50:00 【问题描述】:

尝试执行 linq 查询时出现以下错误:

LINQ to Entities 无法识别“Boolean”方法 IsCharityMatching(System.String, System.String)' 方法和这个 方法无法转换为商店表达式。

我已经阅读了很多以前的问题,人们会遇到同样的错误,如果我理解正确,那是因为 LINQ to Entities 需要将整个 linq 查询表达式转换为服务器查询,因此您不能调用里面有一个外部方法。我还没有能够将我的场景转换成可行的东西,而且我的大脑开始崩溃,所以我希望有人能指出我正确的方向。我们正在使用实体框架和规范模式(我对这两者都很陌生)。

这是使用规范的代码:

ISpecification<Charity> specification = new CharitySearchSpecification(charityTitle, charityReference);

charities = charitiesRepository.Find(specification).OrderBy(p => p.RegisteredName).ToList();

这是 linq 表达式:

public System.Linq.Expressions.Expression<Func<Charity, bool>> IsSatisfied()

    return p => p.IsCharityMatching(this.charityName, this.charityReference);

这是 IsCharityMatching 方法:

public bool IsCharityMatching(string name, string referenceNumber)

    bool exists = true;

    if (!String.IsNullOrEmpty(name))
    
        if (!this.registeredName.ToLower().Contains(name.ToLower()) &&
            !this.alias.ToLower().Contains(name.ToLower()) &&
           !this.charityId.ToLower().Contains(name.ToLower()))
        
            exists = false;
        
    

    if (!String.IsNullOrEmpty(referenceNumber))
    
        if (!this.charityReference.ToLower().Contains(referenceNumber.ToLower()))
        
            exists = false;
        
    

    return exists;

如果您需要更多信息,请告诉我。

非常感谢,

安妮莉

【问题讨论】:

检查this answer 也会检查一下,谢谢! 很高兴看到您如何使用Find(),而您如何在其中使用IsSatisfied() 相关帖子 - LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression & Entity Framework Specification Pattern Implementation 【参考方案1】:

正如您所知道的,Entity Framework 实际上不能将您的 C# 代码作为其查询的一部分运行。它必须能够将查询转换为实际的 SQL 语句。为了使其工作,您必须将查询表达式重组为 Entity Framework 可以处理的表达式。

public System.Linq.Expressions.Expression<Func<Charity, bool>> IsSatisfied()

    string name = this.charityName;
    string referenceNumber = this.referenceNumber;
    return p => 
        (string.IsNullOrEmpty(name) || 
            p.registeredName.ToLower().Contains(name.ToLower()) ||
            p.alias.ToLower().Contains(name.ToLower()) ||
            p.charityId.ToLower().Contains(name.ToLower())) &&
        (string.IsNullOrEmpty(referenceNumber) ||
            p.charityReference.ToLower().Contains(referenceNumber.ToLower()));

【讨论】:

如有疑问请搜索:***.com/questions/2352764/… 返回一个构造的Expression&lt;Func&lt;T,type&gt;&gt; 是一个非常好的方法。 如何在 LINQ 表达式中使用它?我想做这样的事情作为可重复使用的 Where 子句,但正在努力实现它。 编辑:没关系,应该是:context.Where(IsSatisfied()) 关键部分:“实体框架实际上不能将您的 C# 代码作为其查询的一部分运行。”【参考方案2】:

我在这段代码中遇到了同样的错误:

 var articulos_en_almacen = xx.IV00102.Where(iv => alm_x_suc.Exists(axs => axs.almacen == iv.LOCNCODE.Trim())).Select(iv => iv.ITEMNMBR.Trim()).ToList();

这正是错误:

System.NotSupportedException: 'LINQ to Entities 无法识别方法 'Boolean Exists(System.Predicate`1[conector_gp.Models.almacenes_por_sucursal])' 方法,并且此方法无法转换为存储表达式。'

我是这样解决的:

var articulos_en_almacen = xx.IV00102.ToList().Where(iv => alm_x_suc.Exists(axs => axs.almacen == iv.LOCNCODE.Trim())).Select(iv => iv.ITEMNMBR.Trim()).ToList();

我在表格前添加了一个 .ToList(),这将实体和 linq 代码解耦,并避免我的下一个 linq 表达式被翻译

注意:这个解决方案不是最优的,因为避免实体过滤,并且只是将所有表加载到内存中

【讨论】:

大多数时候这是最简单的解决方案,但为了不加载所有对象,我通常在 .ToList() 之前使用我需要的东西进行匿名选择... xx.Select(x=> new x.Id, x.DateTimeUpdate).ToList().Select(x=> new x.Id, DateTimeUpdate = x.DateTimeUpdate.ToString("dd/MM/yyyy") )【参考方案3】:

我今天遇到了同样的问题,这是我点击的第一个链接。但是我不是在寻找验证我的查询。因此,如果其他人有同样的问题并正在寻找此解决方案,则将其添加到此处。我的问题在另一个link。

这是最常见的异常发生在使用实体框架并转换 IQueryable 结果中的数据以进行过滤时。

using (var context = new CustomerContext())

    var item = context.InvoiceItems
        .Where(i => i.Code == code.ToString())
        .FirstOrDefault();

存在多种解决方案。将 ToString() 调用移至单独的行。

using (var context = new CustomerContext())

    string codeStr = code.ToString();
    var item = context.InvoiceItems
        .Where(i => i.Code == codeStr)
        .FirstOrDefault();

使用 EF 扩展方法,

using (var context = new CustomerContext())

    var item = context.InvoiceItems
        .Where(i => i.Code == SqlFunctions.StringConvert(code))
        .FirstOrDefault();

过滤前将 IQueryable 结果转换为 IEnumerable

using (var context = new CustomerContext())

    var item = context.InvoiceItems.AsEnumerable()
        .Where(i => i.Code == code.ToString())
        .FirstOrDefault();

【讨论】:

【参考方案4】:

如果有人正在寻找 VB.Net 的答案(就像我最初一样),这里是:

Public Function IsSatisfied() As Expression(Of Func(Of Charity, String, String, Boolean))

Return Function(charity, name, referenceNumber) (String.IsNullOrWhiteSpace(name) Or
                                                         charity.registeredName.ToLower().Contains(name.ToLower()) Or
                                                         charity.alias.ToLower().Contains(name.ToLower()) Or
                                                         charity.charityId.ToLower().Contains(name.ToLower())) And
                                                    (String.IsNullOrEmpty(referenceNumber) Or
                                                     charity.charityReference.ToLower().Contains(referenceNumber.ToLower()))
End Function

【讨论】:

【参考方案5】:

我在这段代码中遇到了同样的错误:

解决方案

可查询

.toList() 是最佳选择

【讨论】:

以上是关于LINQ to Entities 无法识别该方法的主要内容,如果未能解决你的问题,请参考以下文章

LINQ to Entities 无法识别该方法(在相关实体上)

LINQ to Entities 无法识别方法“System.String ToString()”方法,并且该方法无法转换为存储表达式

我如何修复“LINQ to Entities无法识别方法”错误

LINQ to Entities 无法识别方法“Int32 Parse(System.String)”方法,并且该方法无法转换为存储表达式

LINQ to Entities 无法识别方法“System.Object GetValue(...)”

LINQ to Entities 无法识别“System.String get_Item(Int32)”方法,并且该方法无法转换为存储表达式 [重复]