Eva*_*gle 8 c# lambda linq-to-sql
我有一个班级,用户.
用户具有UserId属性.
我有一个看起来像这样的方法:
static IQueryable<User> FilterById(this IQueryable<User> p, Func<int, bool> sel)
{
return p.Where(m => sel(m.UserId));
}
Run Code Online (Sandbox Code Playgroud)
当我调用函数时,不可避免地:
var users = Users.FilterById(m => m > 10);
Run Code Online (Sandbox Code Playgroud)
我得到以下异常:
方法'System.Object DynamicInvoke(System.Object [])'没有支持的SQL转换.
有没有解决这个问题的方法?Expression.KillMeAndMyFamily()的兔子洞可能需要走多远?
为了澄清我为什么这样做:我使用T4模板自动生成一个简单的存储库和一个管道系统.在管道内,而不是写:
new UserPipe().Where(m => m.UserId > 10 && m.UserName.Contains("oo") && m.LastName == "Wee");
Run Code Online (Sandbox Code Playgroud)
我想生成类似的东西:
new UserPipe()
.UserId(m => m > 10)
.UserName(m => m.Contains("oo"))
.LastName("Wee");
Run Code Online (Sandbox Code Playgroud)
dtb*_*dtb 15
我们UserId以此为例.你想写:
new UserPipe().UserId(uid => uid > 10);
Run Code Online (Sandbox Code Playgroud)
并希望它与以下相同:
new UserPipe().Where(user => user.UserID > 10);
Run Code Online (Sandbox Code Playgroud)
您需要做的是获取第一个版本的表达式树并将其转换为第二个版本.
因此,首先更改签名UserId以接受表达式树而不是编译的lambda:
public static IQueryable<User> UserId(
IQueryable<User> source, Expression<Func<int, bool>> predicate)
Run Code Online (Sandbox Code Playgroud)
然后,编写一个将第一个表达式树转换为第二个版本的方法.我们来看看两个表达式树:
输入:
Lambda
uid
|
BinaryOp
>
/ \
Parameter Constant
uid 10
输出:
Lambda
user
|
BinaryOp
>
/ \
Property Constant
UserID 10
|
Parameter
user
正如你所看到的,所有你需要做的就是把拉姆达的身体,递归来替换参数的所有匹配uid与性能UserId的参数user,并创建与转化体和参数的新lambda表达式user.
您可以使用ExpressionVisitor进行替换.