0

There's the problem I made an Extension method to IQueryable and I want to get property name and value to do a select on it the thing is that I am using Expression tree and try to search rows by the use of Contain() method which is needs a parameter of type string to do the job. my code is doing well while I do the search over string properties but I want this method to do the search on other types like int, decimal, datetime and even booleans so I need to get the property cast it to string and search for the matching values.

what I tried so far is:

        private static readonly MethodInfo _tostring = typeof(Object).GetMethod("ToString") ?? throw new Exception("Cannot create Method");

        public static IQueryable<T> Search<T>(this IQueryable<T> items, string propertyName, string filterValue)
        {
            MethodInfo _compare =
                (((Expression<Func<string, bool>>)(s => s.Contains("aa"))).Body as MethodCallExpression ?? throw new Exception("Cannot Create Method"))
                .Method;
            var property = typeof(T).GetProperty(propertyName) ?? throw new Exception("Couldn't Get the property");
            var row = Expression.Parameter(typeof(T), "row");

            
            Expression prop = Expression.Property(row, property);
            // now making sure if the type is string
            if (property.PropertyType != typeof(string))
            {
                //Here I want to cast it to string but the problem is exactly here anything I try feels like a dead end
                prop = Expression.Call(prop, _tostring);
            }

            var func =
                Expression.Lambda<Func<T, bool>>
                (
                    Expression.Call
                    (
                        prop,
                        _compare,
                        Expression.Constant(filterValue)
                    ),
                    row
                );

            return items.Where(func);
        }
4
  • 1
    Add details which ORM do you use, version and sample of usage. I have answered a tons of such questions and it is easy to correct of your Expression Tree. Commented Nov 29, 2022 at 8:19
  • Your problem is you are attempting to call Object.ToString instead of the correct {PropertyType}.ToString that matches the property's type. You need to find the ToString to call dynamically based on the type of the property e.g. var _tostring = property.PropertyType.GetMethod("ToString"). Commented Nov 29, 2022 at 20:34
  • I'm using EF core 7 by the way I got help from some other guy. lack of experience in Expression trees. I updated the code with the correct solution. Commented Dec 1, 2022 at 8:58
  • @NetMage There's nothing wrong with that call. I should have used polymorphism there was a small mistake now it's completely functional. Commented Dec 1, 2022 at 9:04

1 Answer 1

1

I tried and tested it with some dummy objects; it seems to work.

I refined my answer to use ToString

var prop = Expression.Property(row, property);

Expression expression = prop;

if (prop.Type != typeof(string))
{
   expression = Expression.Call(prop, "ToString", Type.EmptyTypes);
}

var func = Expression.Lambda<Func<T, bool>>
(
     Expression.Call
     (
       expression,
       _compare,
       Expression.Constant(filterValue)
     ),
     row
);

The above expression tree will be compiled to,

If the property type is not a string,

.Where(s => s.property.ToString().Contains("filter")))

If it's a string type,

.Where(s => s.property.Contains("filter")))

Sign up to request clarification or add additional context in comments.

6 Comments

Unfortunately it's not working it throws runtime exception rather than compile time exception.The LINQ expression 'DbSet<Product>()\r\n .Where(f => ((object)f.Name).ToString().Contains(\"Pro\"))' could not be translated. Additional information: Translation of method 'object.ToString' failed.
I see, you are using this for EF queries. This only works for POCO. I will take another look. The error says the LINQ cannot be translated to SQL query.
I did some search, and it turns out that if you want to use LINQ to SQL, EF does not support toString() see github.com/dotnet/efcore/issues/6264
@CharlesHan Actually that issue says it was fixed in EF Core 2
Did you try EF Core 7? you are right that it seems to support ToString() learn.microsoft.com/en-us/ef/core/providers/sql-server/…
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.