c# - 多个运行时过滤器的动态 Linq 查询

标签 c# winforms linq-to-entities

我有一个 winforms 应用程序,它基本上使用 Entity Framework 从数据库加载一堆数据并将其显示在 gridview 上。

对于这种情况,考虑绑定(bind)到 gridview 的实体是这个:

public class Person
{
    public string name;
    public string sex;
    public int age;
}

我想给用户一个选项,通过使用一系列过滤器来过滤 gridview 上的结果,用户可以在这些过滤器上选择他想要过滤的列(年龄、性别、姓名)、运算符(大于、等于、包含等)和值。

过滤器类应该是这样的:

public class filter
{
    public string column;
    public string operator;
    public string value;
}

我的问题是:如何使用动态创建的 linq 查询将这些过滤器应用于显示在 gridview 上的数据?

最佳答案

尝试使用表达式树针对您的数据动态构建 lambda。

这是一个示例实现:

void Main()
{
    var fieldName = "LastName";
    var value = "test";

    var db = new List<Person>() {
        new Person() { name = "fred jones", sex = "male", age = 55 },
        new Person() { name = "samantha jones", sex = "female", age = 45 },
        new Person() { name = "cindy jones", sex = "female", age = 6 }
    };

    // single query
    db.Where( Person.GetFilter("sex", "==", "female").Compile() ).Dump();

    // OR example
    db.Where( 
        PredicateBuilder.Or<Person>(
            Person.GetFilter("sex", "==", "male"), 
            Person.GetFilter("age", "<", 50)
        ).Compile()
    ).Dump();

}
class Person
{
    public string name;
    public string sex;
    public int age;

    public static Expression<Func<Person,bool>> GetFilter<T>(string column, string @operator, T value)
    {
        var ops = new Dictionary<string, Func<Expression, Expression, Expression>>() {
            { "==", (x,y) => Expression.Equal(x,y) },
            { "<=", (x,y) => Expression.LessThanOrEqual(x,y) },
            { ">=", (x,y) => Expression.GreaterThanOrEqual(x,y) },
            { ">", (x,y) => Expression.GreaterThan(x,y) },
            { "<", (x,y) => Expression.LessThan(x,y) },
        };

        var param = Expression.Parameter(typeof(Person));
        var deref = Expression.PropertyOrField(param, column);
        var testval = Expression.Constant(value);

        return Expression.Lambda<Func<Person,bool>>(
            ops[@operator](deref, testval),
            param);
    }
}

请注意,我使用 Linqpad 对此进行了测试,因此请将 .Dump() 调用替换为在您的上下文中适合显示数据的内容。它需要 PredicateBuilder类来构建 OR 或 AND 语句。此外,如果将错误的类型作为值参数传递(例如,比较年龄时传递的字符串,抛出“InvalidOperationException:二元运算符等于未为类型'System.String'和'System.Int32'定义,这也会失败”)。

如果有人能告诉我更好的方法来处理将运算符的字符串表示形式转换为 Expression 类,请告诉我,因为我对上述方法不是很满意,但这是我能想到的最快的方法当时。

关于c# - 多个运行时过滤器的动态 Linq 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6626793/

相关文章:

c# - 系统.InvalidOperationException : Unable to resolve service for type

c# - LINQ 中的 First() 会导致急切加载还是延迟加载?

c# - LINQ 的查询扩展

c# - 从dataGridView插入数据到数据库报错

c# - 在 Windows 2008 上以编程方式创建漫游用户配置文件

c# - Winform 中的通知

c# - FolderBrowserDialog 的替代品

c# - 如何在简单的油漆应用中清除面板

具有递归关系的聚合计数的 LINQ 查询

c# - Paypal 快速结账 : Apply order discount