尝试执行linq查询时出现以下错误:
LINQ to Entities无法识别方法'布尔值 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;
}
如果您需要更多信息,请与我们联系。
非常感谢,
Annelie
答案 0 :(得分:110)
正如您所知,实体框架实际上无法将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()));
}
答案 1 :(得分:0)
我在此代码中遇到了相同的错误:
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表达式被翻译
注意:此解决方案不是最佳解决方案,因为避免了实体过滤,只是将所有表加载到内存中
答案 2 :(得分: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
答案 3 :(得分:0)
我今天遇到了同样的问题,这是我点击的第一个链接。但是,我并不是在寻找验证我的查询。因此,如果其他人有同样的问题并正在寻找此解决方案,则将其添加到此处。我的问题出在另一个 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 :(得分:0)
我在这段代码中遇到了同样的错误:
解决方案
很容易
.toList() 是最佳选择
答案 5 :(得分:-1)
我遇到了与您类似的问题,this LINQ documentation帮助我找到了合适的字符串函数来解决这些限制。