简体   繁体   English

动态构造表达式 <Func<T,bool> &gt;不适用于GreaterThen

[英]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 ). 但是我不仅要更改常量值( 2005 ),而且要更改我的列字段( PublishedYear )。

I am looking for several days how to dynamically build an Expression<Func<,>> . 我正在寻找几天如何动态构建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: 但是在第15行( var body = Expression.Greater... )中引发了异常:

The binary operator GreaterThan is not defined for the types 'System.Nullable`1[System.Int32]' and 'System.Int32'. 没有为类型'System.Nullable'1 [System.Int32]'和'System.Int32'定义二进制运算符GreaterThan。

PS : PS
My column PublishedYear of the table Book is INT NULL or int? 我表的列PublishedYearBookINT NULL还是int? in entity framework class. 在实体框架类中。

The expression w => w.PublishedYear > 2005 so why it keep saying that don't exists this operation? 表达式w => w.PublishedYear > 2005 ,为什么为什么一直说不存在该操作? 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. ...这就是C#代码隐式执行的操作。

If the value NULL for PublishedYear is permitted but does not actually occur, perhaps you can change the type of argument value in both functions to int? 如果PublishedYear的值NULL允许但实际上没有出现,则可以将两个函数中的参数value类型都更改为int? and use value.Value for the comparison in Expression.GreaterThan . 并使用value.Value进行Expression.GreaterThan的比较。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM