【问题标题】:Entity Framework: Using DynamicLinq in a generic filter method实体框架:在通用过滤器方法中使用 DynamicLinq
【发布时间】:2016-07-27 18:58:44
【问题描述】:

我正在使用一种 Filter 方法开发一个大部分通用的应用程序:

IQueryable<T> Filter<T>(IQueryable<T> query, Filter filter) where T : IDataBaseEntity

这里是传入的过滤器对象:

{
    Field: "Header.Title",
    Operator: "contains",
    Value: "asdf"
}

我有一个用于操作符的开关(包含、、== 等)以不同方式处理每个操作符,但在此示例中我将只关注“包含”。

传入的“查询”变量是一个通用接口列表,我的所有 200 个实体都继承自该接口。我什至无法访问此命名空间中的实体类型。

在本例中,“query”参数是实体“Page”的 IQueryable。一个 DynamicLinq for Contains 的典型示例如下:

Expression<Func<Page, bool>> exp = l => l.Contains(filter.Value);
query = query.Where("@0(it)", exp);

但是,我的应用程序的这一部分不是强类型的,我的域不知道“页面”是什么,而是使用继承的 IDataBaseEntity 作为 Func 第一种类型。我收到一个异常,因为“'IDataBaseEntity' 类型中不存在属性或字段 'Header'”。我尝试了各种其他选择,但最终这是主要问题。

注意:出于性能原因,我需要将其保留为 IQueryable,并且不想在任何时候将其变成 IEnumerable。该查询仅在过滤、排序和分页后运行 (.AsEnumerable())。

是否可以对 IQueryable 运行动态 linq,其命名空间中的接口类型对我的实际实体类型一无所知?

【问题讨论】:

    标签: c# entity-framework linq generics dynamic-linq


    【解决方案1】:

    根本不使用界面怎么样 - Dynamic Linq 无论如何都是后期绑定的。您可以在IQueryable&lt;T&gt; 上应用动态Where,结果将为IQueryable&lt;T&gt;。

    只要您可以正确构建字符串谓词,以下应该可以工作:

    query = query.Where("Header.Title.Contains(@0)", filter.Value);
    

    【讨论】:

    • 啊,谢谢。这看起来是 90% 的正确答案,所以我将其标记为正确。给其他阅读这篇文章的人的一些注意事项:方法类型必须是“T:class”,而不是什么都没有或“T:IDataBaseEntity”,否则如果你有一个强类型查询并尝试以 .OfType 结尾() 要通过编译,您将在运行时获得 EF 复杂/原始异常。我还最终使用了 LinqKit 的 query.AsExpandable() 来避免“LINQ to Entities 不支持 LINQ 表达式节点类型 'Invoke'”。不确定 AsExpandable 是否会影响性能或是否有其他方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-20
    • 1970-01-01
    • 2011-06-18
    • 2019-04-14
    • 1970-01-01
    • 2014-12-19
    • 1970-01-01
    相关资源
    最近更新 更多