LINQ to Entities无法识别该方法


116

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

LINQ to Entities无法识别方法“ Boolean IsCharityMatching(System.String,System.String)”方法,并且该方法无法转换为商店表达式。

我已经阅读了很多以前的问题,人们会遇到相同的错误,如果我理解正确,那是因为LINQ to Entities要求将整个linq查询表达式转换为服务器查询,因此您不能调用外部方法在里面。我还无法将情景转换成可以正常使用的东西,而且我的大脑开始融化,所以我希望有人可以指出正确的方向。我们正在使用Entity Framework和规范模式(并且我都是新手)。

这是使用规范的代码:

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

让我知道您是否需要更多信息。

非常感谢,

安妮莉



也会检查一下,谢谢!
annelie

1
很高兴看到您在内部使用Find()时的使用IsSatisfied()方式。
Alisson

Answers:


124

如您所知,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()));
}


2
返回一个构造方法Expression<Func<T,type>>是一种非常好的方法。
特拉维斯J

您将如何在LINQ表达式中使用它?我想做类似这样的事情作为可重用的Where子句,但是正在努力实现它。
Zorgarath

4
编辑:没关系,它将是:context.Where(IsSatisfied())
Zorgarath

关键部分:“实体框架实际上无法在查询中运行C#代码。”
Alper

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(),这将Entity和linq代码解耦,并避免了我的下一个linq表达式被翻译

注意:此解决方案不是最佳解决方案,因为避免实体过滤,而只是将所有表加载到内存中


1
多数情况下,这是最简单的解决方案,但是为了不加载所有对象,我通常在.ToList()之前进行匿名选择,选择所需的东西... xx.Select(x => new {x.Id,x.DateTimeUpdate })。ToList()。Select(x => new {x.Id,DateTimeUpdate = x.DateTimeUpdate.ToString(“ dd / MM / yyyy”)})
Diógenes19年

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.