2
我有一些由EF Core提供的IQuerable集合,我想为它们构建一个动态查询,使用System.Linq.Expressions for Entity将它转换为SQL。c#使用表达式树查询多个集合
IQueryable<ADP> collection1 = _context.Adps;
IQueryable<VHStr> collection2 = _context.VHStrParams;
var q = (from ADP a in collection1
where collection2.Any(p => p.Value.Contains("I") && p.Entid == a.Id)
select a);
var l = q.ToList();
这个工作正常,实体产生正确的SQL。
问题是 - 我如何使用表达式建立这样的查询?我只是想不通我怎么能在第一个的元素构建的表达式来访问另一个集合...
编辑:万一有人发现的,解决的办法是:
IQueryable<ADP> collection1 = _context.Adps;
IQueryable<VHStr> collection2 = _context.VHStrParams;
var q = (from ADP a in collection1
where collection2.Any(p => p.Value.Contains("I") && p.Entid == a.Id)
select a);
var paramExpA = Expression.Parameter(typeof(ADP), "a");
var paramExpV = Expression.Parameter(typeof(VHStr), "v");
var entIdExp = Expression.PropertyOrField(paramExpV, "Entid");
var adpIdExp = Expression.PropertyOrField(paramExpA, "Id");
var convertedAdpIdExp = Expression.Convert(adpIdExp, typeof(long?));
var valueExp = Expression.PropertyOrField(paramExpV, "Value");
var containsStringMethod = typeof(string).GetMethod("Contains", new[] {typeof(string)});
var constValueExp = Expression.Constant("I", typeof(string));
var containsExp = Expression.Call(valueExp, containsStringMethod, constValueExp);
var equalIdsExp = Expression.Equal(entIdExp, convertedAdpIdExp);
var andExp = Expression.AndAlso(containsExp, equalIdsExp);
var lambda1 = Expression.Lambda<Func<VHStr, bool>>(andExp, paramExpV);
var vhstrAnyMethod =
typeof(Queryable)
.GetTypeInfo()
.GetMethods()
.First(m => m.Name == "Any" && m.GetParameters().Count() == 2)
.MakeGenericMethod(typeof(VHStr));
var collection2ConstExpr = Expression.Constant(collection2);
var anyCallExp = Expression.Call(vhstrAnyMethod, collection2ConstExpr, lambda1);
var collection1ConstExpr = Expression.Constant(collection1);
var lambda2 = Expression.Lambda<Func<ADP, bool>>(anyCallExp, paramExpA);
var whereExp = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { typeof(ADP) },
collection1ConstExpr,
lambda2);
var lambda3 = Expression.Lambda<Func<IQueryable<ADP>>>(whereExp);
var resultFunc = lambda3.Compile();
var resultQuerable = resultFunc();
var resultList = resultQuerable.ToList();
的一点是 - 究竟如何我可以添加条件“p.Entid == a.Id”到'dynamically_built_predicate_body',因为它们是来自不同实体的字段? – pushist1y
我认为这很明显。 'p'是上面代码片段中的'anyParam'。 'a'将是另一个你将要创建的'ParameterExpression'(例如'var a = Expression.Parameter(collection1.ElementType,“a”);'并且将被用于使用'anyCall产生'Where'调用的谓词'Expression as body。你应该能够从那里生成具体条件,对于'p.Entid == a.id',它将是'Expression.Equal(Expression.PropertyOrField(anyParam,“Entid”),Expression.PropertyOrField (a,“id”))等。 –
谢谢,Expression.Constant是一个指向正确方向的点。 – pushist1y