代码之家  ›  专栏  ›  技术社区  ›  stucampbell

使用成员访问lambda表达式参数化Linq to SQL谓词

  •  5
  • stucampbell  · 技术社区  · 14 年前

    我有一个查询需要在整个地方重用,我需要改变连接使用的属性/列。

    我想做的是:

    query = RestrictByProp(query, x=>x.ID);
    

    非常简单的 RestrictByProp() 可能是*:

    private static IQueryable<Role> RestrictByProp(IQueryable<Role> query, 
                                                   Func<Role, int> selector)
    {
        return query.Where(x => selector(x) == 1);
    }
    

    问题是,即使是这种简单的实现也会导致运行时异常:

    Method 'System.Object DynamicInvoke(System.Object[])' has no 
    supported translation to SQL.
    

    **(这里我只是添加了一个简单的“where”子句-在我的实际代码中,我将使用lambda来选择用于联接的属性)。*

    我觉得这很奇怪,因为如果成员访问lambda是以内联方式完成的,那么就可以:

     private static IQueryable<Role> RestrictByID(IQueryable<Role> query)
     {
         return query.Where(x=> x.ID == 1);
     }
    

    如果您传入一个 Expression<Func<Role, bool>> (即当参数为 x=>x.ID == 1 )但这会使对象失败,因为我需要在查询中确定右侧操作数的值。

    有没有办法在 RestrictByProp()。 所以linq to sql知道如何生成sql?

    1 回复  |  直到 14 年前
        1
  •  6
  •   Jon Skeet    14 年前

    首先,您需要更改方法签名:

    private static IQueryable<Role> RestrictByProp(IQueryable<Role> query, 
        Expression<Func<Role, int>> selector)
    

    这意味着lambda表达式将转换为表达式树而不是委托。

    然后你需要建立一个 Expression<Func<Role, bool>> 从现有表达式树。

    它会看起来 某物 这样地:

    LambdaExpression lambda = (LambdaExpression) selector;
    var predicate = Expression.Equal(selector, Expression.Constant(1));
    var lambdaPredicate = Expression.Lambda<Func<Role, bool>>(predicate,
                                                              lambda.Parameters);
    return query.Where(lambdaPredicate);