C# Filter IQueryable with ToString

136 Views Asked by At

I have an IQueryable<SomeObject> query which contains a property Value which is a double.

I want to filter it by a string that has dot thousands separator comma before decimal (european).

I've tried the following: query.Where(q => q.Value.ToString("#,##0.00").StartsWith(someValue)

The issue is that it couldnt be translated: Translation of method 'double.ToString' failed. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'.

For my case it is not possible to convert to client evaluation as still need to apply form several other filters to my query. Is there any way to resolve this?

4

There are 4 best solutions below

4
Kamil On

I think ToString() doesnt accept your string format.

It is not the best idea to stringify double, especially when it is a number which is perfect type to use logic with.

Change your:

query.Where(q => q.Value.ToString("#,##0.00").StartsWith(someValue);

to

query.Where(q => q.Value >= someValue && q.Value < someMinimalValue);

then, you want to take values that "starts with" so with values (for 2.11) it can be:

query.Where(q => q.Value >= 2.11 && q.Value < 2.12);
2
ludodev69 On

Entity Framework is not able to translate the ToString method with a custom format into a SQL query. To work around this, you can consider formatting the value before applying the filter. For Example:

string formattedSomeValue = someValue.Replace(".", "").Replace(",", ".");
query = query.Where(q => q.Value.ToString("#,0.00").StartsWith(formattedSomeValue));

In this code, formattedSomeValue is created by replacing the European style thousands separator (dot) with an empty string and the European style decimal separator (comma) with a dot. This way, you can perform the filtering in a way that can be translated by Entity Framework.

Make sure to replace the query variable with the filtered result, as LINQ methods like Where return a new IQueryable object.

Hope it helps!

2
Mohsen Soltanzadeh On

Maybe this is what you want. I just added 'AsQueryable()' before 'Where':

    class Program
    {
        public class Person
        {
            public string Name { get; set; }
            public double Value { get; set; }
        }

        static void Main(string[] args)
        {
            string someValue = "2.3";

            List<Person> people = new List<Person>()
            {
                new Person()
                {
                    Name = "Jack",
                    Value = 2.3
                },
                 new Person()
                {
                    Name = "Nina",
                    Value = 3
                },
                  new Person()
                {
                    Name = "Woody",
                    Value = 2.36589
                },
                   new Person()
                {
                    Name = "David",
                    Value = 10
                   },
            };

            IQueryable<Person> query = people.AsQueryable().Where(q => q.Value.ToString("#,##0.00").StartsWith(someValue));
        }
    }
0
Henrik Eckhoff On

It looks like you're trying to format a double as a string within the LINQ to Entities query, and that's causing a translation issue. The ToString method you're using is not translatable to SQL, which is why it's suggesting client evaluation.

Instead of using ToString within the query, you can try using the SqlFunctions.StringConvert method. Here's an example:

using System.Data.Entity.SqlServer;

// ...

query.Where(q => SqlFunctions.StringConvert((double?)q.Value).Trim().StartsWith(someValue))

This should help in converting the double to a string in a way that can be translated to SQL. The Trim is added to remove trailing spaces that might be introduced during conversion.