Entity Framework: 在通用过滤器方法中使用 DynamicLinq
Entity Framework: Using DynamicLinq in a generic filter method
我正在使用一种过滤器方法开发一个基本通用的应用程序:
IQueryable<T> Filter<T>(IQueryable<T> query, Filter filter) where T : IDataBaseEntity
这是传入的过滤器对象:
{
Field: "Header.Title",
Operator: "contains",
Value: "asdf"
}
我有一个运算符开关(包含、<、>、== 等)以不同方式处理每个运算符,但对于此示例,我将只关注 "contains"。
传入的 "query" 变量是接口的通用列表,我的所有 200 个实体都继承自该接口。我什至无法访问此命名空间中的实体类型。
在此示例中,"query" 参数是实体 "Page" 的 IQueryable。包含的 DynamicLinq 的典型示例如下:
Expression<Func<Page, bool>> exp = l => l.Contains(filter.Value);
query = query.Where("@0(it)", exp);
但是,我的应用程序的这一部分不是强类型的,我的域不知道 "Page" 是什么,而是使用继承的 IDataBaseEntity 作为 Func<> 的第一种类型。我得到一个例外,因为 "No property or field 'Header' exists in type 'IDataBaseEntity'"。我尝试了多种其他选项,但最终发现这是主要问题。
注意:出于性能原因,我需要将其保留为 IQueryable,并且不想在任何时候将其转换为 IEnumerable。查询旨在仅在过滤、排序和分页后为 运行 (.AsEnumerable())。
是否可以 运行 动态 linq 针对 IQueryable,其名称空间中的接口类型对我的实际实体类型一无所知?
根本不使用接口怎么样 - Dynamic Linq 无论如何都是后期绑定的。您可以在 IQueryable<T>
上应用动态 Where
,结果将是 IQueryable<T>
。
只要您可以正确构建字符串谓词,以下操作就应该起作用:
query = query.Where("Header.Title.Contains(@0)", filter.Value);
我正在使用一种过滤器方法开发一个基本通用的应用程序:
IQueryable<T> Filter<T>(IQueryable<T> query, Filter filter) where T : IDataBaseEntity
这是传入的过滤器对象:
{
Field: "Header.Title",
Operator: "contains",
Value: "asdf"
}
我有一个运算符开关(包含、<、>、== 等)以不同方式处理每个运算符,但对于此示例,我将只关注 "contains"。
传入的 "query" 变量是接口的通用列表,我的所有 200 个实体都继承自该接口。我什至无法访问此命名空间中的实体类型。
在此示例中,"query" 参数是实体 "Page" 的 IQueryable。包含的 DynamicLinq 的典型示例如下:
Expression<Func<Page, bool>> exp = l => l.Contains(filter.Value);
query = query.Where("@0(it)", exp);
但是,我的应用程序的这一部分不是强类型的,我的域不知道 "Page" 是什么,而是使用继承的 IDataBaseEntity 作为 Func<> 的第一种类型。我得到一个例外,因为 "No property or field 'Header' exists in type 'IDataBaseEntity'"。我尝试了多种其他选项,但最终发现这是主要问题。
注意:出于性能原因,我需要将其保留为 IQueryable,并且不想在任何时候将其转换为 IEnumerable。查询旨在仅在过滤、排序和分页后为 运行 (.AsEnumerable())。
是否可以 运行 动态 linq 针对 IQueryable,其名称空间中的接口类型对我的实际实体类型一无所知?
根本不使用接口怎么样 - Dynamic Linq 无论如何都是后期绑定的。您可以在 IQueryable<T>
上应用动态 Where
,结果将是 IQueryable<T>
。
只要您可以正确构建字符串谓词,以下操作就应该起作用:
query = query.Where("Header.Title.Contains(@0)", filter.Value);