129

尝试执行 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;
}

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

非常感谢,

安妮莉

4

5 回答 5

137

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

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()));
}
于 2011-08-31T15:43:38.653 回答
1

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

 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 表达式被翻译

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

于 2019-01-14T15:19:36.097 回答
1

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

这是最常见的异常发生在使用实体框架并转换 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();
}
于 2021-03-22T08:32:32.927 回答
0

如果有人正在寻找 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
于 2019-11-14T14:38:09.733 回答
-1

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

解决方案

可查询到

.toList() 是最好的选择

于 2021-05-31T17:16:15.530 回答