【问题标题】:Entity Framework 6 Where Clause Builder Class实体框架 6 Where 子句生成器类
【发布时间】:2013-11-20 01:12:25
【问题描述】:

我创建了一个类来帮助构建 Where 子句的集合,然后创建了一个在使用 Entity Framework 6 代码优先项目中的存储库模式构建查询时应用它们的方法。 Apply 方法的 Equal、NotEqual 和 Contains 部分都可以正常工作。

我的问题或问题是如何将大于和小于子句应用于具有此类实现类型的查询?我让他们在下面对它通常如何为 Linq 查询进行编码,但显然“a”和字段值存在错误。我确实有一个关于类实例化的 TProperty,它应该能够检查并用于转换 FieldValue,因为您不能对某些数据类型使用运算符“>”或“

这是接受通用对象类型和通用属性类型的类。它有一个构造函数,用于创建新实例并在存储中保存多个属性。然后将该列表传递给存储库类,该存储库类循环遍历它们并调用 ApplyWhere 方法以应用于查询。

public class WhereClause<T, TProperty> : IWhereClause<T> where T : class, new()
{
    private string FieldName { get; set; }
    private object FieldValue { get; set; }
    private Enums.WhereOperation WhereOperation { get; set; }

    public WhereClause(string fieldName, object fieldValue, Enums.WhereOperation whereOperation)
    {
        this.FieldName = fieldName;
        this.FieldValue = fieldValue;
        this.WhereOperation = whereOperation;
    }

    public IQueryable<T> ApplyWhere(IQueryable<T> query)
    {
        switch ((int)this.WhereOperation)
        {
            case (int)Enums.WhereOperation.Equal:
                return query.WhereEqual(this.FieldName, this.FieldValue);

            case (int)Enums.WhereOperation.NotEqual:
                return query.WhereNotEqual(this.FieldName, this.FieldValue);

            case (int)Enums.WhereOperation.Contains:
                return query.WhereContains(this.FieldName, this.FieldValue);

           **case (int)Enums.WhereOperation.GreaterThan:
                return query.Where(a => a > this.FieldValue);
            case (int)Enums.WhereOperation.LessThan:
                return query.Where(a => a < this.FieldValue);**
        }
        return query;
    }
}

以下是我如何构建 Where 子句列表以传递到存储库:

IWhereClause<Schema.Model.Product>[] whereClause = new IWhereClause<Schema.Model.Product>[1];
whereClause[0] = new WhereClause<Schema.Model.Product, string>("SKU", "BKL-14244", Enums.WhereOperation.Equal);

这是存储库 Select 方法中的一个 sn-p,它为 IQueryable 查询构建 where 子句:

if (whereClause != null) 
{
    whereClause.ToList().ForEach(one =>
    {
         query = one.ApplyWhere(query);
    });
} 

【问题讨论】:

标签: .net linq entity-framework c#-4.0 repository-pattern


【解决方案1】:

您即将重新发明轮子。 (减去几根辐条?)

如果您认真对待“动态 linq”。 那我建议你拥抱它。使用几种方法中的一种在运行时构建谓词。

  1. 我见过的“最好的”基于字符串的工具是Dynamic linq 在这里讨论。 scott GUs blog on dynamic linq - the string version

  2. 最强大的方式Expression trees 如果您不熟悉表达式树,这将更难做到。 但是您可以构建所需的谓词。

  3. 还有其他方法。对不起,我不能对他们说太多。从未使用过它们。 它们与 1 和/或 2 有一些相似之处。 例如Predicate builder. helps add OR and AND dynamically. 但功能不够强大,无法在您的场景中提供帮助。

  4. 或者您正在尝试的部分自定义解决方案。

您的示例当前正在比较整个类型。所以需要一些工作。 但我建议你不要尝试继续沿着你的道路前进。

.Where(a => a

如果您想研究该主题。 Search for Dynamic Linq in C#

【讨论】:

  • 不幸的是,这些都不是新闻,也没有多大帮助。 #2 和 #4 都是选项,但要寻找一些代码或朝着正确的方向推进。而且您没有解释为什么不推荐#4,只是我不应该继续走这条路。有内置的 Equal 和 NotEqual 函数,似乎大于不应该那么困难,一切都很好,我实现的模式接受这个问题。
  • 我提到了为什么它不起作用。Where(a => a
  • 对不起,我不是想建议你编码 Where(a => this.FieldName 不受新类的限制
  • 我会添加我的评论来解释为什么你正在尝试的东西会很困难
  • 请添加您的查询。WhereNotEqual 和 whereContains 方法
【解决方案2】:

感谢您的建议。正如你所说,它很复杂,所以我最终为任何不为空的搜索参数创建了 Expression> 类型的表达式。不完全通用但足够好,允许我深入了解任何 EF 子导航属性。

然后使用 Expression Visitor 扩展类/方法,我使用 And/Or 运算符将多个表达式组合在一起。然后最后将动态构建的表达式列表应用于 IQueryable 查询,瞧,我的过滤结果。

【讨论】:

  • 确保使用新的日志功能来检查 sql 查询的样子。
猜你喜欢
  • 2011-12-31
  • 1970-01-01
  • 1970-01-01
  • 2011-10-21
  • 2010-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-25
相关资源
最近更新 更多