智能表达翻译

时间:2015-02-05 23:25:58

标签: c# linq entity-framework linq-expressions

我正在创建一个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中的参数属性。

1 个答案:

答案 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;
}