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