【发布时间】:2015-05-04 21:50:24
【问题描述】:
我们正在准备用于过滤记录的动态过滤器。我们应该能够选择一个实体(比如说人),然后根据选择的实体定义过滤器。
设计与此类似。
那么如何设计这样一个可以与任何实体和任何属性一起使用的过滤系统呢?
我们需要使用
- C#
- MVC 5
【问题讨论】:
-
可能使用泛型。
我们正在准备用于过滤记录的动态过滤器。我们应该能够选择一个实体(比如说人),然后根据选择的实体定义过滤器。
设计与此类似。
那么如何设计这样一个可以与任何实体和任何属性一起使用的过滤系统呢?
我们需要使用
【问题讨论】:
我使用 WPF 创建了一个动态过滤器功能,我使用 LINQ To SQL ORM 的方式,使用我的 DataContext 获取所有表及其相应字段 (MetaDataMember) 并使用它构建 UI
IEnumerable<MetaTable> mappedTables = DBContext.Mapping.GetTables();
IEnumerable<MetaDataMember> tablesColumns = mappedTables.SelectMany(t => t.RowType.DataMembers);
然后我为用户使用 MetaDataMember 及其属性创建的每个标准即时构建Expression Trees。
Type entityType = metaDataMember.DeclaringType.Type;
ParameterExpression parameterExpression = Expression.Parameter(entityType, "t"); // t => t; t is the parameterExpression representing the Table type
MemberExpression leftStringExpression = Expression.PropertyOrField(parameterExpression, metaDataMember.Name); // t => t.columnName
然后构建条件,即 Expression.LessThan(等),并使用每个条件的连接表达式(Expression.AndAlso 或 Expression.OrElse)继续为每个条件构建树,最后创建一个 lambda 表达式 Expressions.Lambda并将其传递给 .Where() Linq Extension 方法以获取我的 IQueryable 过滤值并使用它来过滤 UI。
IQueryable<SomeTable> results = DataContext.SomeTable.Where(whereLambdaExpression).Select(selectLambdaExpression);
我采用这种方法的原因是因为在枚举 (results.ToList()) 发生之前查询不会被执行,并且查询是在数据库服务器中执行的,而不是在当前应用程序中。 LINQ 将查询表达式转换为纯 SQL 语句,并且只返回结果。它非常快,因为一切都发生在数据库服务器中。
我无法粘贴我所有的代码,因为它非常庞大,但你明白了它的要点。
【讨论】:
我遇到过这种问题,我通过将文本编译为 LINQ 查询并在数据(集合)上执行并收集结果来解决它。它不会为您提供最佳性能,因为每次它需要动态编译程序集(我已经将它与 100K 行的集合一起使用并且效果很好)。但是,它非常灵活。您可以进一步调整它。代码很长,所以这里是github link。
这里是主要思想:
我分享的 github 链接有一个简单的工作应用程序,其中包含示例和投影。
【讨论】: