139

I'm getting the following error when trying to do a linq query:

LINQ to Entities does not recognize the method 'Boolean IsCharityMatching(System.String, System.String)' method, and this method cannot be translated into a store expression.

I've read lots of previous questions where people get the same error, and if I understand this correctly it's because LINQ to Entities requires the whole linq query expression to be translated to a server query, and therefore you can't call an outside method in it. I haven't been able to convert my scenario into something that works yet, and my brain is starting to melt down, so I was hoping someone could point me in the right direction. We're using Entity Framework and the specification pattern (and I'm new to both).

Here's the code that uses the specification:

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

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

Here's the linq expression:

public System.Linq.Expressions.Expression<Func<Charity, bool>> IsSatisfied()
{
    return p => p.IsCharityMatching(this.charityName, this.charityReference);
}

Here's the IsCharityMatching method:

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

Let me know if you need any more information.

Many thanks,

Annelie

Nivid Dholakia
  • 5,272
  • 4
  • 30
  • 55
annelie
  • 2,569
  • 6
  • 25
  • 39
  • check [this answer](http://stackoverflow.com/questions/7200792/combining-c-code-and-database-code-in-a-specification/7201352#7201352) – Eranga Aug 31 '11 at 15:52
  • 1
    It'd be nice to see how you are using `Find()` when how do you use `IsSatisfied()` inside of it. – Alisson Reinaldo Silva Mar 19 '17 at 03:25
  • Related posts - [LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression](https://stackoverflow.com/q/5899683/465053) & [Entity Framework Specification Pattern Implementation](https://stackoverflow.com/q/2352764/465053) – RBT Mar 01 '19 at 11:36
  • Your question helped me find the answer to mine! Thank you for being thorough in your asking! – 2br-2b Jul 17 '23 at 17:55

5 Answers5

143

As you've figured out, Entity Framework can't actually run your C# code as part of its query. It has to be able to convert the query to an actual SQL statement. In order for that to work, you will have to restructure your query expression into an expression that Entity Framework can handle.

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()));
}
StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
1

I got the same error in this code:

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

This was the exact error I received:

System.NotSupportedException: 'LINQ to Entities does not recognize the method 'Boolean Exists(System.Predicate`1[conector_gp.Models.almacenes_por_sucursal])' method, and this method cannot be translated into a store expression.'

I solved it this way:

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();

I added a .ToList() after my table. This decoupled the Entity and linq code and prevents my next linq expression from being translated to sql.

NOTE: this solution isn't optimal, because it loads the entire table into memory before filtering it down.

2br-2b
  • 395
  • 2
  • 5
  • 13
Ing. Gerardo Sánchez
  • 1,607
  • 15
  • 14
  • 5
    Most of time this the easiest solution but to not load all the object i usually make a anonymous select before the .ToList() with just what i need... xx.Select(x=> new { x.Id, x.DateTimeUpdate}).ToList().Select(x=> new { x.Id, DateTimeUpdate = x.DateTimeUpdate.ToString("dd/MM/yyyy") }) – Diógenes Jan 22 '19 at 17:57
1

I ran into the same problem today, this was the first link I hit. However I was not looking for verifying my query. So if somebody else has the same issue and are looking for this solution it is added here. My issue was in another link.

It is the most common exception occurs when working with entity framework and converting data inside IQueryable result for filtering.

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

Several solutions exist. Move ToString() call to a separate line.

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

Use EF Extension Method,

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

Convert IQueryable result to IEnumerable before Filtering

using (var context = new CustomerContext())
{
    var item = context.InvoiceItems.AsEnumerable()
        .Where(i => i.Code == code.ToString())
        .FirstOrDefault();
}
JTIM
  • 2,774
  • 1
  • 34
  • 74
0

If anyone is looking for a VB.Net answer (as I was initially), here it is:

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
Mik
  • 3,998
  • 2
  • 26
  • 16
-3

I got the same error in this code:

Solution

IQueryable to .toList() is the best option

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Sameer Bahad
  • 555
  • 5
  • 4