我正在创建一个IQueryable,我希望将其用于传递给实体框架的查询。我的存储库不公开可查询。
var query = new List<Entity>().AsQueryable().Where(x => x.Property == "argument");
我的存储库中有一个方法可以接收IQueryable。
如何使用相同的可查询来查询我的DbSet?我试图从可查询中提取表达式为dbset构建一个新的表达式。这是我到目前为止所做的,但它不起作用:
public IDbSet<TEntity> DbSet { get; set; }
public IEnumerable<TEntity> Find(IQueryable<TEntity> queryable)
{
var parameter = Expression.Parameter(typeof (TEntity));
var body = queryable.Expression;
var lambda = Expression.Lambda<Func<TEntity, bool>>(body, parameter);
var result = DbSet.Where(lambda);
return null;
}
当我尝试使用以下错误创建lambda时代码失败: 类型'System.Linq.IQueryable`1 [MyTEntity]'的表达式不能用于返回类型'System.Boolean'
我显然没有正确构建表达式,我缺少什么?有没有更简单的方法来完成我想要完成的任务?
此外,我已经看到一些示例表明Expression应该具有参数属性。但无论我转换为什么类型的表达式类型,并且这个类型是ConstantExpression,我都没有看到IQueryable.Expression中的参数属性。
答案 0 :(得分:3)
在您的情况下,queryable.Expression
代表整个表达式Queryable.Where(constantList, x => x.Property == "argument")
。如果你只想要Where()
lambda,你需要提取它。为此,您可以使用以下代码:
public IEnumerable<TEntity> Find<TEntity>(IQueryable<TEntity> queryable)
{
var methodCall = queryable.Expression as MethodCallExpression;
Func<IQueryable<TEntity>, Expression<Func<TEntity,Boolean>>, IQueryable<TEntity>> whereDelegate = Queryable.Where;
if (methodCall.Method == whereDelegate.Method
&& methodCall.Arguments[0] is ConstantExpression)
{
var whereLambdaQuote = (UnaryExpression)methodCall.Arguments[1];
var whereLambda = (Expression<Func<TEntity, bool>>)whereLambdaQuote.Operand;
var result = DbSet.Where(whereLambda);
}
return null;
}