Ejemplo n.º 1
0
        TableBuilder.TableContext GetTableContext(IBuildContext ctx, Expression path, out Expression?stopExpression)
        {
            stopExpression = null;

            var table = ctx as TableBuilder.TableContext;

            if (table != null)
            {
                return(table);
            }

            if (ctx is LoadWithContext lwCtx)
            {
                return(lwCtx.TableContext);
            }

            if (table == null)
            {
                var isTableResult = ctx.IsExpression(null, 0, RequestFor.Table);
                if (isTableResult.Result)
                {
                    table = isTableResult.Context as TableBuilder.TableContext;
                    if (table != null)
                    {
                        return(table);
                    }
                }
            }

            var maxLevel = path.GetLevel(ctx.Builder.MappingSchema);
            var level    = 1;

            while (level <= maxLevel)
            {
                var levelExpression = path.GetLevelExpression(ctx.Builder.MappingSchema, level);
                var isTableResult   = ctx.IsExpression(levelExpression, 1, RequestFor.Table);
                if (isTableResult.Result)
                {
                    table = isTableResult.Context switch
                    {
                        TableBuilder.TableContext t => t,
                        AssociationContext a => a.TableContext as TableBuilder.TableContext,
                                                  _ => null
                    };

                    if (table != null)
                    {
                        stopExpression = levelExpression;
                        return(table);
                    }
                }

                ++level;
            }

            var expr = path.GetLevelExpression(ctx.Builder.MappingSchema, 0);

            throw new LinqToDBException(
                      $"Unable to find table information for LoadWith. Consider moving LoadWith closer to GetTable<{expr.Type.Name}>() method.");
        }
Ejemplo n.º 2
0
        public static TableBuilder.TableContext?GetTableContext(IBuildContext context)
        {
            var table = context as TableBuilder.TableContext;

            if (table != null)
            {
                return(table);
            }

            if (context is LoadWithBuilder.LoadWithContext lwCtx)
            {
                return(lwCtx.TableContext);
            }

            if (table == null)
            {
                var isTableResult = context.IsExpression(null, 0, RequestFor.Table);
                if (isTableResult.Result)
                {
                    table = isTableResult.Context as TableBuilder.TableContext;
                    if (table != null)
                    {
                        return(table);
                    }
                }
            }

            return(null);
        }
Ejemplo n.º 3
0
        static void BuildSetter(
            ExpressionBuilder builder,
            IBuildContext into,
            List <SelectQuery.SetExpression> items,
            IBuildContext ctx,
            MemberInitExpression expression,
            Expression path)
        {
            foreach (var binding in expression.Bindings)
            {
                var member = binding.Member;

                if (member is MethodInfo)
                {
                    member = ((MethodInfo)member).GetPropertyInfo();
                }

                if (binding is MemberAssignment)
                {
                    var ma = binding as MemberAssignment;
                    var pe = Expression.MakeMemberAccess(path, member);

                    if (ma.Expression is MemberInitExpression && !into.IsExpression(pe, 1, RequestFor.Field).Result)
                    {
                        BuildSetter(
                            builder,
                            into,
                            items,
                            ctx,
                            (MemberInitExpression)ma.Expression, Expression.MakeMemberAccess(path, member));
                    }
                    else
                    {
                        var column = into.ConvertToSql(pe, 1, ConvertFlags.Field);
                        var expr   = builder.ConvertToSqlExpression(ctx, ma.Expression);

                        if (expr.ElementType == QueryElementType.SqlParameter)
                        {
                            var parm  = (SqlParameter)expr;
                            var field = column[0].Sql is SqlField
                                                                ? (SqlField)column[0].Sql
                                                                : (SqlField)((SelectQuery.Column)column[0].Sql).Expression;

                            if (parm.DataType == DataType.Undefined)
                            {
                                parm.DataType = field.DataType;
                            }
                        }

                        items.Add(new SelectQuery.SetExpression(column[0].Sql, expr));
                    }
                }
                else
                {
                    throw new InvalidOperationException();
                }
            }
        }
Ejemplo n.º 4
0
        public bool IsExpression(Expression expression, int level, RequestFor testFlag)
        {
            switch (testFlag)
            {
            case RequestFor.SubQuery: return(true);
            }

            return(SubQuery.IsExpression(expression, level, testFlag));
        }
Ejemplo n.º 5
0
        static void BuildSetter(
            ExpressionBuilder builder,
            IBuildContext into,
            List <SqlQuery.SetExpression> items,
            IBuildContext ctx,
            MemberInitExpression expression,
            Expression path)
        {
            foreach (var binding in expression.Bindings)
            {
                var member = binding.Member;

                if (member is MethodInfo)
                {
                    member = TypeHelper.GetPropertyByMethod((MethodInfo)member);
                }

                if (binding is MemberAssignment)
                {
                    var ma = binding as MemberAssignment;
                    var pe = Expression.MakeMemberAccess(path, member);

                    if (ma.Expression is MemberInitExpression && !into.IsExpression(pe, 1, RequestFor.Field).Result)
                    {
                        BuildSetter(
                            builder,
                            into,
                            items,
                            ctx,
                            (MemberInitExpression)ma.Expression, Expression.MakeMemberAccess(path, member));
                    }
                    else
                    {
                        var column = into.ConvertToSql(pe, 1, ConvertFlags.Field);
                        var expr   = builder.ConvertToSqlExpression(ctx, ma.Expression, false);

                        if (expr is SqlValueBase && TypeHelper.IsEnumOrNullableEnum(ma.Expression.Type))
                        {
                            var memberAccessor = TypeAccessor.GetAccessor(ma.Member.DeclaringType)[ma.Member.Name];
                            ((SqlValueBase)expr).SetEnumConverter(memberAccessor, builder.MappingSchema);
                        }

                        items.Add(new SqlQuery.SetExpression(column[0].Sql, expr));
                    }
                }
                else
                {
                    throw new InvalidOperationException();
                }
            }
        }
Ejemplo n.º 6
0
        TableBuilder.TableContext?GetTableContext(IBuildContext ctx)
        {
            var table = ctx as TableBuilder.TableContext;

            if (table == null)
            {
                var isTableResult = ctx.IsExpression(null, 0, RequestFor.Table);
                if (isTableResult.Result)
                {
                    table = isTableResult.Context as TableBuilder.TableContext;
                }
            }

            return(table);
        }
Ejemplo n.º 7
0
        static void BuildSetter(
            ExpressionBuilder builder,
            IBuildContext into,
            List <SqlQuery.SetExpression> items,
            IBuildContext ctx,
            MemberInitExpression expression,
            Expression path)
        {
            foreach (var binding in expression.Bindings)
            {
                var member = binding.Member;

                if (member is MethodInfo)
                {
                    member = ((MethodInfo)member).GetPropertyInfo();
                }

                if (binding is MemberAssignment)
                {
                    var ma = binding as MemberAssignment;
                    var pe = Expression.MakeMemberAccess(path, member);

                    if (ma.Expression is MemberInitExpression && !into.IsExpression(pe, 1, RequestFor.Field).Result)
                    {
                        BuildSetter(
                            builder,
                            into,
                            items,
                            ctx,
                            (MemberInitExpression)ma.Expression, Expression.MakeMemberAccess(path, member));
                    }
                    else
                    {
                        var column = into.ConvertToSql(pe, 1, ConvertFlags.Field);
                        var expr   = builder.ConvertToSqlExpression(ctx, ma.Expression);

                        items.Add(new SqlQuery.SetExpression(column[0].Sql, expr));
                    }
                }
                else
                {
                    throw new InvalidOperationException();
                }
            }
        }
            void CheckAndAddMember(IBuildContext sequence1, IBuildContext sequence2, SqlInfo info)
            {
                var member = new Member
                {
                    SequenceInfo     = info,
                    MemberExpression = Expression.PropertyOrField(_unionParameter, info.Members[0].Name)
                };

                if (sequence1.IsExpression(member.MemberExpression, 1, RequestFor.Object).Result)
                {
                    throw new LinqException("Types in {0} are constructed incompatibly.", _methodCall.Method.Name);
                }

                var idx = sequence2.ConvertToIndex(member.MemberExpression, 1, ConvertFlags.Field);

                if (idx[0].Index != member.SequenceInfo.Index)
                {
                    throw new LinqException("Types in {0} are constructed incompatibly.", _methodCall.Method.Name);
                }

                _members.Add(member.MemberExpression.Member, member);
            }
Ejemplo n.º 9
0
        public Expression BuildMultipleQuery(IBuildContext context, Expression expression)
        {
            if (!Common.Configuration.Linq.AllowMultipleQuery)
            {
                throw new LinqException("Multiple queries are not allowed. Set the 'LinqToDB.Common.Configuration.Linq.AllowMultipleQuery' flag to 'true' to allow multiple queries.");
            }

            var parameters = new HashSet <ParameterExpression>();

            expression.Visit(e =>
            {
                if (e.NodeType == ExpressionType.Lambda)
                {
                    foreach (var p in ((LambdaExpression)e).Parameters)
                    {
                        parameters.Add(p);
                    }
                }
            });

            // Convert associations.
            //
            expression = expression.Transform(e =>
            {
                switch (e.NodeType)
                {
                case ExpressionType.MemberAccess:
                    {
                        var root = e.GetRootObject();

                        if (root != null &&
                            root.NodeType == ExpressionType.Parameter &&
                            !parameters.Contains((ParameterExpression)root))
                        {
                            var res = context.IsExpression(e, 0, RequestFor.Association);

                            if (res.Result)
                            {
                                var table = (TableBuilder.AssociatedTableContext)res.Context;

                                if (table.IsList)
                                {
                                    var ttype  = typeof(Table <>).MakeGenericType(table.ObjectType);
                                    var tbl    = Activator.CreateInstance(ttype);
                                    var method = typeof(LinqExtensions)
                                                 .GetMethod("Where", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static)
                                                 .MakeGenericMethod(e.Type, table.ObjectType, ttype);

                                    var me = (MemberExpression)e;
                                    var op = Expression.Parameter(table.ObjectType, "t");

                                    parameters.Add(op);

                                    Expression ex = null;

                                    for (var i = 0; i < table.Association.ThisKey.Length; i++)
                                    {
                                        var field1 = table.ParentAssociation.SqlTable.Fields[table.Association.ThisKey [i]];
                                        var field2 = table.SqlTable.Fields[table.Association.OtherKey[i]];

                                        var ee = Expression.Equal(
                                            Expression.MakeMemberAccess(op, field2.ColumnDescriptor.MemberInfo),
                                            Expression.MakeMemberAccess(me.Expression, field1.ColumnDescriptor.MemberInfo));

                                        ex = ex == null ? ee : Expression.AndAlso(ex, ee);
                                    }

                                    return(Expression.Call(null, method, Expression.Constant(tbl), Expression.Lambda(ex, op)));
                                }
                            }
                        }

                        break;
                    }
                }

                return(e);
            });

            var paramex = Expression.Parameter(typeof(object[]), "ps");
            var parms   = new List <Expression>();

            // Convert parameters.
            //
            expression = expression.Transform(e =>
            {
                var root = e.GetRootObject();

                if (root != null &&
                    root.NodeType == ExpressionType.Parameter &&
                    !parameters.Contains((ParameterExpression)root))
                {
                    var ex = Expression.Convert(BuildExpression(context, e), typeof(object));

                    parms.Add(ex);

                    return(Expression.Convert(
                               Expression.ArrayIndex(paramex, Expression.Constant(parms.Count - 1)),
                               e.Type));
                }

                return(e);
            });

            var sqtype = typeof(MultipleQueryHelper <>).MakeGenericType(expression.Type);
            var helper = (IMultipleQueryHelper)Activator.CreateInstance(sqtype);

            return(helper.GetSubquery(this, expression, paramex, parms));
        }
Ejemplo n.º 10
0
        static Expression GetMultipleQueryExpression(IBuildContext context, MappingSchema mappringSchema, Expression expression, HashSet <ParameterExpression> parameters)
        {
            if (!Common.Configuration.Linq.AllowMultipleQuery)
            {
                throw new LinqException("Multiple queries are not allowed. Set the 'LinqToDB.Common.Configuration.Linq.AllowMultipleQuery' flag to 'true' to allow multiple queries.");
            }

            expression.Visit(e =>
            {
                if (e.NodeType == ExpressionType.Lambda)
                {
                    foreach (var p in ((LambdaExpression)e).Parameters)
                    {
                        parameters.Add(p);
                    }
                }
            });

            // Convert associations.
            //
            return(expression.Transform(e =>
            {
                switch (e.NodeType)
                {
                case ExpressionType.MemberAccess:
                    {
                        var root = e.GetRootObject();

                        if (root != null &&
                            root.NodeType == ExpressionType.Parameter &&
                            !parameters.Contains((ParameterExpression)root))
                        {
                            var res = context.IsExpression(e, 0, RequestFor.Association);

                            if (res.Result)
                            {
                                var table = (TableBuilder.AssociatedTableContext)res.Context;

                                if (table.IsList)
                                {
                                    var ttype = typeof(Table <>).MakeGenericType(table.ObjectType);
                                    var tbl = Activator.CreateInstance(ttype, context.Builder.DataContext);
                                    var method = e == expression ?
                                                 MemberHelper.MethodOf <IEnumerable <bool> >(n => n.Where(a => a)).GetGenericMethodDefinition().MakeGenericMethod(table.ObjectType) :
                                                 _whereMethodInfo.MakeGenericMethod(e.Type, table.ObjectType, ttype);

                                    var me = (MemberExpression)e;
                                    var op = Expression.Parameter(table.ObjectType, "t");

                                    parameters.Add(op);

                                    Expression ex = null;

                                    for (var i = 0; i < table.Association.ThisKey.Length; i++)
                                    {
                                        var field1 = table.ParentAssociation.SqlTable.Fields[table.Association.ThisKey [i]];
                                        var field2 = table.SqlTable.Fields[table.Association.OtherKey[i]];

                                        var ma1 = Expression.MakeMemberAccess(op, field2.ColumnDescriptor.MemberInfo);
                                        var ma2 = Expression.MakeMemberAccess(me.Expression, field1.ColumnDescriptor.MemberInfo);

                                        var ee = Equal(mappringSchema, ma1, ma2);

                                        ex = ex == null ? ee : Expression.AndAlso(ex, ee);
                                    }

                                    var expr = Expression.Call(null, method, Expression.Constant(tbl), Expression.Lambda(ex, op));

                                    if (e == expression)
                                    {
                                        expr = Expression.Call(
                                            MemberHelper.MethodOf <IEnumerable <int> >(n => n.ToList()).GetGenericMethodDefinition().MakeGenericMethod(table.ObjectType),
                                            expr);
                                    }

                                    return expr;
                                }
                            }
                        }

                        break;
                    }
                }

                return e;
            }));
        }
        static Expression GetMultipleQueryExpressionLazy(IBuildContext context, MappingSchema mappingSchema, Expression expression, HashSet <ParameterExpression> parameters)
        {
            expression.Visit(e =>
            {
                if (e.NodeType == ExpressionType.Lambda)
                {
                    foreach (var p in ((LambdaExpression)e).Parameters)
                    {
                        parameters.Add(p);
                    }
                }
            });

            // Convert associations.
            //
            return(expression.Transform(e =>
            {
                switch (e.NodeType)
                {
                case ExpressionType.MemberAccess :
                    {
                        var root = e.GetRootObject(mappingSchema);

                        if (root != null &&
                            root.NodeType == ExpressionType.Parameter &&
                            !parameters.Contains((ParameterExpression)root))
                        {
                            var res = context.IsExpression(e, 0, RequestFor.Association);

                            if (res.Result)
                            {
                                var table = (TableBuilder.AssociatedTableContext)res.Context !;

                                if (table.IsList)
                                {
                                    var me = (MemberExpression)e;
                                    Expression expr;

                                    var parentType = me.Expression.Type;
                                    var childType = table.ObjectType;

                                    var queryMethod = table.Association.GetQueryMethod(parentType, childType);
                                    if (queryMethod != null)
                                    {
                                        //TODO: MARS
                                        var dcConst = Expression.Constant(context.Builder.DataContext.Clone(true));

                                        expr = queryMethod.GetBody(me.Expression, dcConst);
                                    }
                                    else
                                    {
                                        var ttype = typeof(Table <>).MakeGenericType(childType);
                                        var tbl = Activator.CreateInstance(ttype, context.Builder.DataContext);
                                        var method = e == expression ?
                                                     MemberHelper.MethodOf <IEnumerable <bool> >(n => n.Where(a => a)).GetGenericMethodDefinition().MakeGenericMethod(childType) :
                                                     _whereMethodInfo.MakeGenericMethod(e.Type, childType, ttype);

                                        var op = Expression.Parameter(childType, "t");

                                        parameters.Add(op);

                                        Expression?ex = null;

                                        for (var i = 0; i < table.Association.ThisKey.Length; i++)
                                        {
                                            var field1 = table.ParentAssociation.SqlTable.Fields[table.Association.ThisKey [i]];
                                            var field2 = table.SqlTable.Fields[table.Association.OtherKey[i]];

                                            var ma1 = Expression.MakeMemberAccess(op, field2.ColumnDescriptor.MemberInfo);
                                            var ma2 = Expression.MakeMemberAccess(me.Expression, field1.ColumnDescriptor.MemberInfo);

                                            var ee = Equal(mappingSchema, ma1, ma2);

                                            ex = ex == null ? ee : Expression.AndAlso(ex, ee);
                                        }

                                        var predicate = table.Association.GetPredicate(parentType, childType);
                                        if (predicate != null)
                                        {
                                            var body = predicate.GetBody(me.Expression, op);
                                            ex = ex == null ? body : Expression.AndAlso(ex, body);
                                        }

                                        if (ex == null)
                                        {
                                            throw new LinqToDBException($"Invalid association configuration for {table.Association.MemberInfo.DeclaringType}.{table.Association.MemberInfo.Name}");
                                        }

                                        expr = Expression.Call(null, method, Expression.Constant(tbl), Expression.Lambda(ex, op));
                                    }

                                    if (e == expression)
                                    {
                                        expr = Expression.Call(
                                            MemberHelper.MethodOf <IEnumerable <int> >(n => n.ToList()).GetGenericMethodDefinition().MakeGenericMethod(childType),
                                            expr);
                                    }

                                    return expr;
                                }
                            }
                        }

                        break;
                    }
                }

                return e;
            }));
        }
Ejemplo n.º 12
0
        static Expression GetMultipleQueryExpressionLazy(IBuildContext context, MappingSchema mappingSchema, Expression expression, HashSet <ParameterExpression> parameters)
        {
            expression.Visit(e =>
            {
                if (e.NodeType == ExpressionType.Lambda)
                {
                    foreach (var p in ((LambdaExpression)e).Parameters)
                    {
                        parameters.Add(p);
                    }
                }
            });

            // Convert associations.
            //
            return(expression.Transform(e =>
            {
                switch (e.NodeType)
                {
                case ExpressionType.MemberAccess :
                    {
                        var root = context.Builder.GetRootObject(e);

                        if (root != null &&
                            root.NodeType == ExpressionType.Parameter &&
                            !parameters.Contains((ParameterExpression)root))
                        {
                            var res = context.IsExpression(e, 0, RequestFor.Association);

                            if (res.Result)
                            {
                                var associationContext = (AssociationContext)res.Context !;

                                if (associationContext.Descriptor.IsList)
                                {
                                    var me = (MemberExpression)e;

                                    var parentType = me.Expression.Type;
                                    var childType = me.Type;

                                    var queryMethod = AssociationHelper.CreateAssociationQueryLambda(context.Builder,
                                                                                                     new AccessorMember(me), associationContext.Descriptor, parentType, parentType, childType, false,
                                                                                                     false, null, out _);

                                    var dcConst = Expression.Constant(context.Builder.DataContext.Clone(true));

                                    var expr = queryMethod.GetBody(me.Expression, dcConst);

                                    if (e == expression)
                                    {
                                        expr = Expression.Call(
                                            Methods.Enumerable.ToList.MakeGenericMethod(childType),
                                            expr);
                                    }

                                    return expr;
                                }
                            }
                        }

                        break;
                    }
                }

                return e;
            }));
        }
Ejemplo n.º 13
0
 public override IsExpressionResult IsExpression(Expression?expression, int level, RequestFor requestFlag)
 => _source.IsExpression(expression, level, requestFlag);
        static Expression GetMultipleQueryExpression(IBuildContext context, MappingSchema mappingSchema, Expression expression, HashSet <ParameterExpression> parameters)
        {
            if (!Common.Configuration.Linq.AllowMultipleQuery)
            {
                throw new LinqException("Multiple queries are not allowed. Set the 'LinqToDB.Common.Configuration.Linq.AllowMultipleQuery' flag to 'true' to allow multiple queries.");
            }

            expression.Visit(e =>
            {
                if (e.NodeType == ExpressionType.Lambda)
                {
                    foreach (var p in ((LambdaExpression)e).Parameters)
                    {
                        parameters.Add(p);
                    }
                }
            });

            // Convert associations.
            //
            return(expression.Transform(e =>
            {
                switch (e.NodeType)
                {
                case ExpressionType.MemberAccess:
                    {
                        var root = e.GetRootObject(mappingSchema);

                        if (root != null &&
                            root.NodeType == ExpressionType.Parameter &&
                            !parameters.Contains((ParameterExpression)root))
                        {
                            var res = context.IsExpression(e, 0, RequestFor.Association);

                            if (res.Result)
                            {
                                var table = (TableBuilder.AssociatedTableContext)res.Context;

                                if (table.IsList)
                                {
                                    var me = (MemberExpression)e;
                                    Expression expr;

                                    var parentType = me.Expression.Type;
                                    var childType = table.ObjectType;

                                    var queryMethod = table.Association.GetQueryMethod(parentType, childType);
                                    if (queryMethod != null)
                                    {
                                        var parentParam = Expression.Parameter(parentType, "o");
                                        var ptype = typeof(Table <>).MakeGenericType(parentType);
                                        var ptbl = Activator.CreateInstance(ptype, context.Builder.DataContext);

                                        var principalExpression = Expression.Constant(ptbl);
                                        var selectMany = (MethodCallExpression)table.GetAssociationQueryExpression(Expression.Constant(context.Builder.DataContext), null,
                                                                                                                   parentType, principalExpression, queryMethod);

                                        var parentDescriptor = mappingSchema.GetEntityDescriptor(parentType);

                                        var keyColumns = parentDescriptor.Columns.Where(c => c.IsPrimaryKey).ToList();
                                        if (keyColumns.Count == 0)
                                        {
                                            keyColumns = parentDescriptor.Columns;
                                        }

                                        var arguments = selectMany.Arguments.ToList();

                                        Expression predicate = null;
                                        foreach (var column in keyColumns)
                                        {
                                            var ee = Expression.Equal(
                                                Expression.MakeMemberAccess(
                                                    parentParam, column.MemberInfo),
                                                Expression.MakeMemberAccess(
                                                    root, column.MemberInfo));
                                            predicate = predicate == null ? ee : Expression.AndAlso(predicate, ee);
                                        }

                                        if (predicate == null)
                                        {
                                            throw new LinqToDBException($"Invalid mapping for Principal Entity during association building. Association {table.Association.MemberInfo.DeclaringType}.{table.Association.MemberInfo.Name}");
                                        }

                                        var filteredQuery = Expression.Call(null,
                                                                            _queryableMethodInfo.MakeGenericMethod(parentType), arguments[0], Expression.Lambda(predicate, parentParam));

                                        arguments[0] = filteredQuery;
                                        selectMany = selectMany.Update(selectMany.Object, arguments);

                                        var asQueryable = MemberHelper
                                                          .MethodOf((IQueryable <object> q) => LinqExtensions.AsQueryable <object, object>(0))
                                                          .GetGenericMethodDefinition()
                                                          .MakeGenericMethod(e.Type, selectMany.Type);

                                        expr = Expression.Call(null,
                                                               asQueryable, selectMany);
                                    }
                                    else
                                    {
                                        var ttype = typeof(Table <>).MakeGenericType(childType);
                                        var tbl = Activator.CreateInstance(ttype, context.Builder.DataContext);
                                        var method = e == expression ?
                                                     MemberHelper.MethodOf <IEnumerable <bool> >(n => n.Where(a => a)).GetGenericMethodDefinition().MakeGenericMethod(childType) :
                                                     _whereMethodInfo.MakeGenericMethod(e.Type, childType, ttype);

                                        var op = Expression.Parameter(childType, "t");

                                        parameters.Add(op);

                                        Expression ex = null;

                                        for (var i = 0; i < table.Association.ThisKey.Length; i++)
                                        {
                                            var field1 = table.ParentAssociation.SqlTable.Fields[table.Association.ThisKey [i]];
                                            var field2 = table.SqlTable.Fields[table.Association.OtherKey[i]];

                                            var ma1 = Expression.MakeMemberAccess(op, field2.ColumnDescriptor.MemberInfo);
                                            var ma2 = Expression.MakeMemberAccess(me.Expression, field1.ColumnDescriptor.MemberInfo);

                                            var ee = Equal(mappingSchema, ma1, ma2);

                                            ex = ex == null ? ee : Expression.AndAlso(ex, ee);
                                        }

                                        var predicate = table.Association.GetPredicate(parentType, childType);
                                        if (predicate != null)
                                        {
                                            var body = predicate.GetBody(me.Expression, op);
                                            ex = ex == null ? body : Expression.AndAlso(ex, body);
                                        }

                                        if (ex == null)
                                        {
                                            throw new LinqToDBException($"Invalid association configuration for {table.Association.MemberInfo.DeclaringType}.{table.Association.MemberInfo.Name}");
                                        }

                                        expr = Expression.Call(null, method, Expression.Constant(tbl), Expression.Lambda(ex, op));
                                    }

                                    if (e == expression)
                                    {
                                        expr = Expression.Call(
                                            MemberHelper.MethodOf <IEnumerable <int> >(n => n.ToList()).GetGenericMethodDefinition().MakeGenericMethod(childType),
                                            expr);
                                    }

                                    return expr;
                                }
                            }
                        }

                        break;
                    }
                }

                return e;
            }));
        }