我有以下表达式:
public Expression<Func<T, bool>> UserAccessCheckExpression<T>(int userId) where T : class
{
return x => (IsAdmin || userId == CurrentUserId || userId == 0);
}
然后我想将此过滤器应用于几个集合(IQueryable),如下所示:
return tasks
.Where(t => t.TaskUsers
.Any(x => UserAccessCheckExpression<TaskUser>(x.User) && x.SomeBool == true));
执行此操作时出现以下错误:
错误40无法将类型
System.Linq.Expressions.Expression<System.Func<TaskUser,bool>>
隐式转换为bool
我无法使用接口继承的解决方法(比如TaskUser继承了带有int UserId属性的接口(其中T:IHasUserId)),因为我想要组合逻辑。
答案 0 :(得分:2)
问题是,当UserAccessCheckExpression()
方法期待Expression
时,您的Any()
方法返回boolean
。
现在,您可以通过编译Expression
并调用方法(使用UserAccessCheckExpression<TaskUser>(x.User).Compile().Invoke(x.User))
来获取编译的代码,但这显然会在运行时失败,因为Linq-to-实体无法将您的Any()
翻译为商店查询,因为它不再包含Expression
。
LinqKit旨在使用自己的Invoke
扩展方法来解决此问题,该方法允许您的代码编译,同时确保您的Expression
将被替换回其原始格式名为AsExpandable()
的扩展方法,用于扩展实体集。
试试这个:
using LinqKit.Extensions;
return tasks
.AsExpandable()
.Where(t => t.TaskUsers.Any(
x => UserAccessCheckExpression<TaskUser>(x.User).Invoke(x)
&& x.SomeBool == true));
答案 1 :(得分:0)
是的,所以,你不能这样做。 Expression<>
和Func<>
之间存在差异。您正在尝试使用UserAccessCheckExpression
作为功能。我不确定你要做什么,但你可以把它编译成一个函数,然后像你一样使用它:
var expr = UserAccessCheckExpression<TaskUser>(x.User);
var func = expr.Compile();
// Later use it like ...
var result = func();
但是我希望你在EF或Linq2Sql中使用它?在这种情况下,您需要重写表达式。它可以手工完成(不容易),或者更好,使用像PredicateBuilder这样的工具。