コード例 #1
0
 protected abstract IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall,
                                                  BuildInfo buildInfo);
コード例 #2
0
 protected abstract SequenceConvertInfo Convert(ExpressionBuilder builder, MethodCallExpression methodCall,
                                                BuildInfo buildInfo, ParameterExpression param);
コード例 #3
0
 public bool IsSequence(ExpressionBuilder builder, BuildInfo buildInfo)
 {
     return
         (builder.IsSequence(new BuildInfo(buildInfo, ((MethodCallExpression)buildInfo.Expression).Arguments[0])));
 }
コード例 #4
0
 protected abstract bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall,
                                            BuildInfo buildInfo);
コード例 #5
0
 public IBuildContext BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
 {
     return(BuildMethodCall(builder, (MethodCallExpression)buildInfo.Expression, buildInfo));
 }
コード例 #6
0
 public SequenceConvertInfo Convert(ExpressionBuilder builder, BuildInfo buildInfo, ParameterExpression param)
 {
     return(Convert(builder, (MethodCallExpression)buildInfo.Expression, buildInfo, param));
 }
コード例 #7
0
 public SequenceConvertInfo Convert(ExpressionBuilder builder, BuildInfo buildInfo, ParameterExpression param)
 {
     return(null);
 }
コード例 #8
0
        private IBuildContext GetSubQueryContext(ExpressionBuilder builder, MethodCallExpression methodCall,
                                                 BuildInfo buildInfo,
                                                 ISelectQuery sql,
                                                 LambdaExpression innerKeyLambda,
                                                 Expression outerKeySelector,
                                                 Expression innerKeySelector,
                                                 IBuildContext outerKeyContext)
        {
            var subQueryContext =
                builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SelectQuery()));

            subQueryContext = new SubQueryContext(subQueryContext);

            var subQueryParent     = subQueryContext.Parent;
            var subQueryKeyContext = new ExpressionContext(buildInfo.Parent, subQueryContext, innerKeyLambda);

            // Process SubQuery.
            //
            var subQuerySql = ((SubQueryContext)subQueryContext).Select;

            // Make join and where for the counter.
            //
            if (outerKeySelector.NodeType == ExpressionType.New)
            {
                var new1 = (NewExpression)outerKeySelector;
                var new2 = (NewExpression)innerKeySelector;

                for (var i = 0; i < new1.Arguments.Count; i++)
                {
                    var arg1 = new1.Arguments[i];
                    var arg2 = new2.Arguments[i];

                    BuildSubQueryJoin(builder, outerKeyContext, arg1, arg2, subQueryKeyContext, subQuerySql);
                }
            }
            else if (outerKeySelector.NodeType == ExpressionType.MemberInit)
            {
                var mi1 = (MemberInitExpression)outerKeySelector;
                var mi2 = (MemberInitExpression)innerKeySelector;

                for (var i = 0; i < mi1.Bindings.Count; i++)
                {
                    if (mi1.Bindings[i].Member != mi2.Bindings[i].Member)
                    {
                        throw new LinqException(
                                  "List of member inits does not match for entity type '{0}'.".Args(outerKeySelector.Type));
                    }

                    var arg1 = ((MemberAssignment)mi1.Bindings[i]).Expression;
                    var arg2 = ((MemberAssignment)mi2.Bindings[i]).Expression;

                    BuildSubQueryJoin(builder, outerKeyContext, arg1, arg2, subQueryKeyContext, subQuerySql);
                }
            }
            else
            {
                BuildSubQueryJoin(builder, outerKeyContext, outerKeySelector, innerKeySelector, subQueryKeyContext,
                                  subQuerySql);
            }

            builder.ReplaceParent(subQueryKeyContext, subQueryParent);

            subQuerySql.ParentSelect = sql;
            subQuerySql.Select.Columns.Clear();

            return(subQueryContext);
        }
コード例 #9
0
ファイル: OfTypeBuilder.cs プロジェクト: forki/bars2db
 protected override SequenceConvertInfo Convert(
     ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param)
 {
     return(null);
 }
コード例 #10
0
 public bool CanBuild(ExpressionBuilder builder, BuildInfo buildInfo)
 {
     return(buildInfo.Expression is ChangeTypeExpression);
 }
コード例 #11
0
ファイル: ConcatUnionBuilder.cs プロジェクト: forki/bars2db
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall,
                                            BuildInfo buildInfo)
 {
     return(methodCall.Arguments.Count == 2 && methodCall.IsQueryable("Concat", "Union"));
 }
コード例 #12
0
ファイル: PassThroughBuilder.cs プロジェクト: forki/bars2db
 protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall,
                                                  BuildInfo buildInfo)
 {
     return(builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])));
 }
コード例 #13
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall,
                                                         BuildInfo buildInfo)
        {
            var isGroup      = methodCall.Method.Name == "GroupJoin";
            var outerContext =
                builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0], buildInfo.SelectQuery));
            var innerContext =
                builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SelectQuery()));

            var context = new SubQueryContext(outerContext);

            innerContext = isGroup ? new GroupJoinSubQueryContext(innerContext) : new SubQueryContext(innerContext);

            var join = isGroup ? innerContext.Select.WeakLeftJoin() : innerContext.Select.InnerJoin();
            var sql  = context.Select;

            sql.From.Tables.First.Value.Joins.AddLast(join.JoinedTable);

            var selector = (LambdaExpression)methodCall.Arguments[4].Unwrap();

            context.SetAlias(selector.Parameters[0].Name);
            innerContext.SetAlias(selector.Parameters[1].Name);

            var outerKeyLambda = (LambdaExpression)methodCall.Arguments[2].Unwrap();
            var innerKeyLambda = (LambdaExpression)methodCall.Arguments[3].Unwrap();

            var outerKeySelector = outerKeyLambda.Body.Unwrap();
            var innerKeySelector = innerKeyLambda.Body.Unwrap();

            var outerParent = context.Parent;
            var innerParent = innerContext.Parent;

            var outerKeyContext = new ExpressionContext(buildInfo.Parent, context, outerKeyLambda);
            var innerKeyContext = new InnerKeyContext(buildInfo.Parent, innerContext, innerKeyLambda);

            // Make join and where for the counter.
            //
            if (outerKeySelector.NodeType == ExpressionType.New)
            {
                var new1 = (NewExpression)outerKeySelector;
                var new2 = (NewExpression)innerKeySelector;

                for (var i = 0; i < new1.Arguments.Count; i++)
                {
                    var arg1 = new1.Arguments[i];
                    var arg2 = new2.Arguments[i];

                    BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2);
                }
            }
            else if (outerKeySelector.NodeType == ExpressionType.MemberInit)
            {
                var mi1 = (MemberInitExpression)outerKeySelector;
                var mi2 = (MemberInitExpression)innerKeySelector;

                for (var i = 0; i < mi1.Bindings.Count; i++)
                {
                    if (mi1.Bindings[i].Member != mi2.Bindings[i].Member)
                    {
                        throw new LinqException(
                                  "List of member inits does not match for entity type '{0}'.".Args(outerKeySelector.Type));
                    }

                    var arg1 = ((MemberAssignment)mi1.Bindings[i]).Expression;
                    var arg2 = ((MemberAssignment)mi2.Bindings[i]).Expression;

                    BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2);
                }
            }
            else
            {
                BuildJoin(builder, join, outerKeyContext, outerKeySelector, innerKeyContext, innerKeySelector);
            }

            builder.ReplaceParent(outerKeyContext, outerParent);
            builder.ReplaceParent(innerKeyContext, innerParent);

            if (isGroup)
            {
                var inner = (GroupJoinSubQueryContext)innerContext;

                inner.Join = join.JoinedTable;
                inner.GetSubQueryContext = () =>
                                           GetSubQueryContext(builder, methodCall, buildInfo, sql,
                                                              innerKeyLambda, outerKeySelector, innerKeySelector, outerKeyContext);

                return(new GroupJoinContext(
                           buildInfo.Parent, selector, context, inner, methodCall.Arguments[1], outerKeyLambda, innerKeyLambda));
            }

            return(new JoinContext(buildInfo.Parent, selector, context, innerContext)
#if DEBUG
            {
                MethodCall = methodCall
            }
#endif
                   );
        }
コード例 #14
0
ファイル: TakeSkipBuilder.cs プロジェクト: forki/bars2db
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall,
                                            BuildInfo buildInfo)
 {
     return(methodCall.IsQueryable("Skip", "Take"));
 }
コード例 #15
0
 private ISequenceBuilder GetBuilder(ExpressionBuilder builder, BuildInfo buildInfo)
 {
     return(_builder ?? (_builder = builder.GetBuilder(buildInfo)));
 }
コード例 #16
0
ファイル: SelectBuilder.cs プロジェクト: forki/bars2db
        protected override SequenceConvertInfo Convert(
            ExpressionBuilder builder, MethodCallExpression originalMethodCall, BuildInfo buildInfo,
            ParameterExpression param)
        {
            var methodCall = originalMethodCall;
            var selector   = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var info       = builder.ConvertSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]), selector.Parameters[0]);

            if (info != null)
            {
                methodCall = (MethodCallExpression)methodCall.Transform(
                    ex => ConvertMethod(methodCall, 0, info, selector.Parameters[0], ex));
                selector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            }

            if (param != null && !ReferenceEquals(param, builder.SequenceParameter))
            {
                var list =
                    GetExpressions(selector.Parameters[0], param, 0, selector.Body.Unwrap())
                    .OrderByDescending(path => path.Level)
                    .ToList();

                if (list.Count > 0)
                {
                    var plist = list.Where(e => ReferenceEquals(e.Expr, selector.Parameters[0])).ToList();

                    if (plist.Count > 1)
                    {
                        list = list.Except(plist.Skip(1)).ToList();
                    }

                    var p = plist.FirstOrDefault();

                    if (p == null)
                    {
                        var types  = methodCall.Method.GetGenericArguments();
                        var mgen   = methodCall.Method.GetGenericMethodDefinition();
                        var btype  = typeof(ExpressionHoder <,>).MakeGenericType(types[0], selector.Body.Type);
                        var fields = btype.GetFieldsEx();
                        var pold   = selector.Parameters[0];
                        var psel   = Expression.Parameter(types[0], pold.Name);

                        methodCall = Expression.Call(
                            methodCall.Object,
                            mgen.MakeGenericMethod(types[0], btype),
                            methodCall.Arguments[0],
                            Expression.Lambda(
                                Expression.MemberInit(
                                    Expression.New(btype),
                                    Expression.Bind(fields[0], psel),
                                    Expression.Bind(fields[1], selector.Body.Transform(e => e == pold ? psel : e))),
                                psel));

                        selector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
                        param    = Expression.Parameter(selector.Body.Type, param.Name);

                        list.Add(new SequenceConvertPath
                        {
                            Path  = param,
                            Expr  = Expression.MakeMemberAccess(param, fields[1]),
                            Level = 1
                        });

                        var expr = Expression.MakeMemberAccess(param, fields[0]);

                        foreach (var t in list)
                        {
                            t.Expr = t.Expr.Transform(ex => ReferenceEquals(ex, pold) ? expr : ex);
                        }

                        return(new SequenceConvertInfo
                        {
                            Parameter = param,
                            Expression = methodCall,
                            ExpressionsToReplace = list
                        });
                    }

                    if (info?.ExpressionsToReplace != null)
                    {
                        foreach (var path in info.ExpressionsToReplace)
                        {
                            path.Path   = path.Path.Transform(e => ReferenceEquals(e, info.Parameter) ? p.Path : e);
                            path.Expr   = path.Expr.Transform(e => ReferenceEquals(e, info.Parameter) ? p.Path : e);
                            path.Level += p.Level;

                            list.Add(path);
                        }

                        list = list.OrderByDescending(path => path.Level).ToList();
                    }

                    if (list.Count > 1)
                    {
                        return(new SequenceConvertInfo
                        {
                            Parameter = param,
                            Expression = methodCall,
                            ExpressionsToReplace = list
                                                   .Where(e => !ReferenceEquals(e, p))
                                                   .Select(ei =>
                            {
                                ei.Expr = ei.Expr.Transform(e => ReferenceEquals(e, p.Expr) ? p.Path : e);
                                return ei;
                            })
                                                   .ToList()
                        });
                    }
                }
            }

            if (!ReferenceEquals(methodCall, originalMethodCall))
            {
                return new SequenceConvertInfo
                       {
                           Parameter  = param,
                           Expression = methodCall
                       }
            }
            ;

            return(null);
        }
コード例 #17
0
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall,
                                            BuildInfo buildInfo)
 {
     return(methodCall.IsQueryable("Where", "Having"));
 }