我已经玩了好几个小时,可以使用一双新鲜的眼睛。好的,有关表达树的经验比我更多的人。男人的曲线很陡!
考虑以下内容。 (这有效,但我需要将帐户作为字符串传递。帐户是帐户列表)
repo = repo.Where(x => x.Accounts.FirstOrDefault().Id == AccountId);
这是我到目前为止所做的。
var parameterExp = Expression.Parameter(typeof(Boat), "x");
var propertyExp = Expression.Property(parameterExp, "Accounts");
MethodInfo method1 = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).First(m => m.Name == "FirstOrDefault");
// This gives me a Queryable of Account FirstOrDefault
var specificMethod = method1.MakeGenericMethod(propertyExp.Type);
// right here is where I am getting stuck
var firstOrDefaultAccountExpression = // I need to get an Account so I can query against the Id ??
MethodInfo method = typeof(long).GetMethod("Equals", new[] { typeof(long) });
var someValue = Expression.Constant(AccountId, typeof(long));
var containsMethodExp = Expression.Call(firstOrDefaultAccountExpression , method, someValue);
Expression<Func<Boat, bool>> predicate = Expression.Lambda<Func<Boat, bool>>
(containsMethodExp, parameterExp);
repo = repo.Where(predicate);
我能够将此代码用于常规字符串成员。我似乎无法弄清楚清单。最终我试图找回一个BoatId = long
的船只清单提前致谢!
答案 0 :(得分:1)
var parameterExp = Expression.Parameter(typeof(Boat), "x");
Expression propertyExp = Expression.Property(parameterExp, "Accounts");
Type elementType = propertyExp.Type.GetGenericArguments()[0];
MethodInfo method1 = typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static).First(m => m.Name == "FirstOrDefault");
// This gives me a Queryable of Account FirstOrDefault
var specificMethod = method1.MakeGenericMethod(elementType);
//propertyExp = Expression.TypeAs(propertyExp, typeof(IEnumerable<>).MakeGenericType(elementType));
var firstOrDefaultAccountExpression = Expression.Call(specificMethod, propertyExp);
var idExpr = Expression.PropertyOrField(firstOrDefaultAccountExpression, "Id");
MethodInfo method = typeof(long).GetMethod("Equals", new[] { typeof(long) });
var someValue = Expression.Constant(AccountId, typeof(long));
var containsMethodExp = Expression.Call(idExpr, method, someValue);
Expression<Func<Boat, bool>> predicate = Expression.Lambda<Func<Boat, bool>>
(containsMethodExp, parameterExp);
repo = repo.Where(predicate);
我会发誓,如果没有演员阵容就行不通,但现在它工作,奇怪。所以我评论了这条线。但在两个版本中它都能够在linq2sql中生成sql代码,我测试了它。您不需要Queryable来访问Accounts属性(我不确定是否可以)。查看代码的第一行,即非表达式查询。即便如此,List<>
必须投放到IEnumerable<>
才能调用FirstOrDefault
。FirstOrDefault
也是Enumerable
的方法。它的目的是通过定义表达式来定义转换,而不是实际做任何事情的函数。