public Expression GetExpression(Expression parent, AssociatedTableContext association) { Expression expr = null; var param = Expression.Parameter(typeof(T), "c"); foreach (var cond in (association).ParentAssociationJoin.Condition.Conditions) { var p = (SelectQuery.Predicate.ExprExpr)cond.Predicate; var e1 = Expression.MakeMemberAccess(parent, ((SqlField)p.Expr1).ColumnDescriptor.MemberInfo); Expression e2 = Expression.MakeMemberAccess(param, ((SqlField)p.Expr2).ColumnDescriptor.MemberInfo); while (e1.Type != e2.Type) { if (e1.Type.IsNullable()) { e1 = Expression.PropertyOrField(e1, "Value"); continue; } if (e2.Type.IsNullable()) { e2 = Expression.PropertyOrField(e2, "Value"); continue; } e2 = Expression.Convert(e2, e1.Type); } var ex = Expression.Equal(e1, e2); expr = expr == null ? ex : Expression.AndAlso(expr, ex); } var predicate = Expression.Lambda <Func <T, bool> >(expr, param); return(association.Builder.DataContextInfo.DataContext.GetTable <T>().Where(predicate).Expression); }
public Expression GetSubquery( ExpressionBuilder builder, AssociatedTableContext tableContext, ParameterExpression parentObject) { var lContext = Expression.Parameter(typeof(IDataContext), "ctx"); var lParent = Expression.Parameter(typeof(object), "parentObject"); Expression expression; var queryMethod = tableContext.Association.GetQueryMethod(parentObject.Type, typeof(T)); if (queryMethod != null) { var ownerParam = queryMethod.Parameters[0]; var dcParam = queryMethod.Parameters[1]; var ownerExpr = Expression.Convert(lParent, parentObject.Type); expression = queryMethod.Body.Transform(e => e == ownerParam ? ownerExpr : (e == dcParam ? lContext : e)); } else { var tableExpression = builder.DataContext.GetTable <T>(); var loadWith = tableContext.GetLoadWith(); if (loadWith != null) { foreach (var members in loadWith) { var pLoadWith = Expression.Parameter(typeof(T), "t"); var isPrevList = false; Expression obj = pLoadWith; foreach (var member in members) { if (isPrevList) { obj = new GetItemExpression(obj); } obj = Expression.MakeMemberAccess(obj, member); isPrevList = typeof(IEnumerable).IsSameOrParentOf(obj.Type); } tableExpression = tableExpression.LoadWith(Expression.Lambda <Func <T, object> >(obj, pLoadWith)); } } // Where var pWhere = Expression.Parameter(typeof(T), "t"); Expression expr = null; for (var i = 0; i < tableContext.Association.ThisKey.Length; i++) { var thisProp = Expression.PropertyOrField(Expression.Convert(lParent, parentObject.Type), tableContext.Association.ThisKey[i]); var otherProp = Expression.PropertyOrField(pWhere, tableContext.Association.OtherKey[i]); var ex = ExpressionBuilder.Equal(tableContext.Builder.MappingSchema, otherProp, thisProp); expr = expr == null ? ex : Expression.AndAlso(expr, ex); } var predicate = tableContext.Association.GetPredicate(parentObject.Type, typeof(T)); if (predicate != null) { var ownerParam = predicate.Parameters[0]; var childParam = predicate.Parameters[1]; var ownerExpr = Expression.Convert(lParent, parentObject.Type); var body = predicate.Body.Transform(e => e == ownerParam ? ownerExpr : (e == childParam ? pWhere : e)); expr = expr == null ? body : Expression.AndAlso(expr, body); } expression = tableExpression.Where(Expression.Lambda <Func <T, bool> >(expr, pWhere)).Expression; } var lambda = Expression.Lambda <Func <IDataContext, object, IEnumerable <T> > >(expression, lContext, lParent); var queryReader = CompiledQuery.Compile(lambda); expression = Expression.Call( null, MemberHelper.MethodOf(() => ExecuteSubQuery(null, null, null)), ExpressionBuilder.QueryRunnerParam, Expression.Convert(parentObject, typeof(object)), Expression.Constant(queryReader)); var memberType = tableContext.Association.MemberInfo.GetMemberType(); if (memberType == typeof(T[])) { return(Expression.Call(null, MemberHelper.MethodOf(() => Enumerable.ToArray <T>(null)), expression)); } if (memberType.IsSameOrParentOf(typeof(List <T>))) { return(Expression.Call(null, MemberHelper.MethodOf(() => Enumerable.ToList <T>(null)), expression)); } var ctor = memberType.GetConstructorEx(new[] { typeof(IEnumerable <T>) }); if (ctor != null) { return(Expression.New(ctor, expression)); } var l = builder.MappingSchema.GetConvertExpression(expression.Type, memberType, false, false); if (l != null) { return(l.GetBody(expression)); } throw new LinqToDBException($"Expected constructor '{memberType.Name}(IEnumerable<{tableContext.ObjectType}>)'"); }