Dynamically constructing an Expression<Func<T,bool>> doesn't work for GreaterThen

Hi I have a simple query in Entity Framework:

using (var db = new BookstoreContext())
{
    return db.Book
        .Where(w => w.PublishedYear > 2005)
        .ToList();
}

Now I want to change this query to something more dynamic. But I want to change, not only the constant value (2005) but also my column field (PublishedYear).

I am looking for several days how to dynamically build an Expression<Func<,>>. Now i found this page and I'm trying to do so. So far I came to this:

public IEnumerable<Book> GetBooksGreaterThan(string columnName, object value)
{
    using (var db = new BookstoreContext())
    {
        return  db.Book
            .Where(GreaterThan(columnName, value))
            .ToList();
    }
}

public Expression<Func<Book, bool>> GreaterThan(string columnName, object value)
{
    var param = Expression.Parameter(typeof(Book), "w");
    var property = Expression.PropertyOrField(param, columnName);
    var body = Expression.GreaterThan(property, Expression.Constant(value));

    return Expression.Lambda<Func<Book, bool>>(body, param);
}

But in line 15 (var body = Expression.Greater...) a exception is thrown:

The binary operator GreaterThan is not defined for the types 'System.Nullable`1[System.Int32]' and 'System.Int32'.

PS:
My column PublishedYear of the table Book is INT NULL or int? in entity framework class.

The expression w => w.PublishedYear > 2005 so why it keep saying that don't exists this operation? How can I fix it?

Jon Skeet
people
quotationmark

The problem is the nullability. You could probably get away with just adding a conversion expression from the value to the type of the property:

public Expression<Func<Book, bool>> GreaterThan(string columnName, object value)
{
    var param = Expression.Parameter(typeof(Book), "w");
    var property = Expression.PropertyOrField(param, columnName);
    var propertyType = typeof(Book).GetProperty(columnName).PropertyType;
    var body = Expression.GreaterThan(property,
         Expression.Convert(Expression.Constant(value), propertyType));

    return Expression.Lambda<Func<Book, bool>>(body, param);
}

This is now effectively doing:

w => w.PublishedYear > (int?) 2005

... which is what the C# code is doing implicitly.

people

See more on this question at Stackoverflow