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?
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.
See more on this question at Stackoverflow