LINQtoEntity 不识别该方法

在尝试执行 linq 查询时,我得到了以下错误:

LINQtoEntity 不识别方法‘ Boolean’ (System.String,System.String)的方法,以及这个 方法无法转换为存储表达式。

我读过很多以前的问题,其中人们得到相同的错误,如果我理解正确,这是因为 LINQ 到实体需要整个 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);
}

以下是 IsCharitymatch 方法:

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

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

非常感谢,

安妮莉

156620 次浏览

正如您已经发现的,实体框架实际上不能将您的 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()));
}

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

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

这正是错误所在:

系统。NotSupportedException: ‘ LINQtoEntity 不识别方法’Boolean Exists (System。谓词‘1[ conector _ gp。方法,该方法不能转换为存储表达式

我是这样解决的:

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

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

如果有人正在寻找一个 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

我今天遇到了同样的问题,这是我碰到的第一个链接。然而,我没有寻找验证我的查询。因此,如果其他人有同样的问题,并正在寻找这个解决方案,它被添加到这里。我的问题是在另一个 链接里。

当使用实体框架并在 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 结果转换为 IEnumable

using (var context = new CustomerContext())
{
var item = context.InvoiceItems.AsEnumerable()
.Where(i => i.Code == code.ToString())
.FirstOrDefault();
}

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

解决方案

IQueryable.toList()是最佳选择