//p=>p
        //p=>p.t
        //p=>p.Id
        protected override Expression VisitLambda <T>(Expression <T> node)
        {
            LambdaExpression lambda = node as LambdaExpression;

            if (lambda.Body.NodeType == ExpressionType.Parameter)
            {
                // expression like a=> a
                Type   type  = lambda.Body.Type;
                string alias = _aliases.GetTableAlias(lambda);
                this.VisitAllMember(type, alias);
                return(node);
            }

            if (lambda.Body.NodeType == ExpressionType.MemberAccess)
            {
                // expression like t=> t.a
                // => SELECT a.ClientId
                Type type = lambda.Body.Type;
                return(TypeUtils.IsPrimitive(type)
                    ? base.VisitLambda(node)
                    : this.VisitAllMember(type, _aliases.GetTableAlias(lambda.Body), node));
            }

            if (_mOnly)
            {
                _mOnly = false;
            }
            return(base.VisitLambda(node));
        }
Пример #2
0
        // 获取 LEFT JOIN / INNER JOIN 子句关联表的的别名
        private void GetLfInJoinAlias(DbExpression exp, TableAliasCache aliases)
        {
            Type   type = exp.Expressions[0].Type.GetGenericArguments()[0];
            string name = TypeRuntimeInfoCache.GetRuntimeInfo(type).TableName;

            // on a.Name equals b.Name 或 on new{ Name = a.Name,Id=a.Id } equals new { Name = b.Name,Id=b.Id }
            LambdaExpression left  = exp.Expressions[1] as LambdaExpression;
            LambdaExpression right = exp.Expressions[2] as LambdaExpression;
            NewExpression    body1 = left.Body as NewExpression;

            if (body1 == null)
            {
                aliases.GetTableAlias(exp.Expressions[1]);
                string alias = aliases.GetTableAlias(exp.Expressions[2]);

                // 记录显示指定的LEFT JOIN 表别名
                aliases.AddOrUpdateJoinTableAlias(name, alias);
            }
            else
            {
                NewExpression body2 = right.Body as NewExpression;
                for (int index = 0; index < body1.Arguments.Count; ++index)
                {
                    aliases.GetTableAlias(body1.Arguments[index]);
                    string alias = aliases.GetTableAlias(body2.Arguments[index]);

                    // 记录显示指定的LEFT JOIN 表别名
                    aliases.AddOrUpdateJoinTableAlias(name, alias);
                }
            }
        }
        // LEFT OR INNER JOIN
        private void AppendLfInJoin(SqlBuilder builder, DbExpression exp, TableAliasCache aliases)
        {
            // [TableName]
            //var constExp = exp.Expressions[0] as ConstantExpression;
            //constExp.Type.GetGenericArguments()[0]
            //var queryable = constExp.Value as IDbQueryable;
            //var innerExp = queryable.DbExpressions[0];
            //if (innerExp.DbExpressionType != DbExpressionType.GetTable) throw new XfwException("inner expression must be GetTable<T> expression");
            //Type type = (innerExp.Expression as ConstantExpression).Value as Type;

            Type type = exp.Expressions[0].Type.GetGenericArguments()[0];

            builder.Append(' ');
            builder.AppendMember(TypeRuntimeInfoCache.GetRuntimeInfo(type).TableName);

            LambdaExpression left  = exp.Expressions[1] as LambdaExpression;
            LambdaExpression right = exp.Expressions[2] as LambdaExpression;
            NewExpression    body1 = left.Body as NewExpression;
            NewExpression    body2 = right.Body as NewExpression;

            // t0(t1)
            string alias = body1 == null
                ? aliases.GetTableAlias(exp.Expressions[2])
                : aliases.GetTableAlias(body2.Arguments[0]);

            builder.Append(' ');
            builder.Append(alias);
            builder.Append(' ');

            // ON a.Name = b.Name AND a.Id = b.Id
            builder.Append("ON ");

            if (body1 == null)
            {
                builder.AppendMember(aliases, left.Body.ReduceUnary());
                builder.Append(" = ");
                builder.AppendMember(aliases, right.Body.ReduceUnary());
            }
            else
            {
                for (int index = 0; index < body1.Arguments.Count; ++index)
                {
                    builder.AppendMember(aliases, body1.Arguments[index]);
                    builder.Append(" = ");
                    builder.AppendMember(aliases, body2.Arguments[index]);
                    if (index < body1.Arguments.Count - 1)
                    {
                        builder.Append(" AND ");
                    }
                }
            }
        }
Пример #4
0
        /// <summary>
        /// 追加列名
        /// </summary>
        /// <param name="aliases">表别名</param>
        /// <param name="expression">列名表达式</param>
        /// <returns>返回解析到的表别名</returns>
        public string AppendMember(TableAliasCache aliases, Expression expression)
        {
            Expression       exp = expression;
            LambdaExpression lambdaExpression = exp as LambdaExpression;

            if (lambdaExpression != null)
            {
                exp = lambdaExpression.Body;
            }

            MemberExpression memExp = exp as MemberExpression;

            if (expression.NodeType == ExpressionType.Constant || memExp.Expression.NodeType == ExpressionType.Constant)
            {
                PartialVisitor visitor = new PartialVisitor();
                var            eval    = visitor.Eval(memExp ?? expression);
                string         value   = eval.NodeType == ExpressionType.Constant
                    ? ExpressionVisitorBase.GetSqlValue((eval as ConstantExpression).Value)
                    : string.Empty;
                _builder.Append(value);

                return(value);
            }
            else
            {
                string alias = aliases == null ? null : aliases.GetTableAlias(memExp);
                this.AppendMember(alias, memExp.Member.Name);
                return(alias);
            }
        }
Пример #5
0
        // 获取 CROSS JOIN 子句关联表的的别名
        private void GetCrossJoinAlias(DbExpression exp, TableAliasCache aliases)
        {
            LambdaExpression lambdaExp = exp.Expressions[1] as LambdaExpression;

            for (int index = 0; index < lambdaExp.Parameters.Count; ++index)
            {
                aliases.GetTableAlias(lambdaExp.Parameters[index]);
            }
        }
        // Cross Join
        private void AppendCrossJoin(SqlBuilder builder, DbExpression exp, TableAliasCache aliases)
        {
            LambdaExpression lambdaExp = exp.Expressions[1] as LambdaExpression;
            Type             type      = lambdaExp.Parameters[1].Type;

            builder.Append(' ');
            builder.AppendMember(TypeRuntimeInfoCache.GetRuntimeInfo(type).TableName);

            string alias = aliases.GetTableAlias(lambdaExp.Parameters[1]);

            builder.Append(' ');
            builder.Append(alias);
            builder.Append(' ');
        }
Пример #7
0
        protected virtual void VisitNavigation(Expression node, string memberName = null)
        {
            // 表达式 => b.Client.Address.AddressName
            Expression f = node;
            Stack <KeyValuePair <string, MemberExpression> > stack = null;

            while (f != null && f.IsVisitable())
            {
                if (f.NodeType != ExpressionType.MemberAccess)
                {
                    break;
                }

                if (stack == null)
                {
                    stack = new Stack <KeyValuePair <string, MemberExpression> >();
                }
                MemberExpression m            = f as MemberExpression;
                var runtime                   = TypeRuntimeInfoCache.GetRuntimeInfo(m.Expression.Type);
                ForeignKeyAttribute attribute = runtime.GetWrapperAttribute <ForeignKeyAttribute>(m.Member.Name);
                if (attribute == null)
                {
                    break;
                }

                string key = m.GetKeyWidthoutAnonymous();
                stack.Push(new KeyValuePair <string, MemberExpression>(key, m));
                f = m.Expression;
            }

            if (stack != null && stack.Count > 0)
            {
                while (stack != null && stack.Count > 0)
                {
                    KeyValuePair <string, MemberExpression> kvp = stack.Pop();
                    string           key = kvp.Key;
                    MemberExpression m   = kvp.Value;

                    var runtime = TypeRuntimeInfoCache.GetRuntimeInfo(m.Type);
                    // 检查查询表达式是否显示指定该表关联
                    string alias = _aliases.GetJoinTableAlias(runtime.TableName);
                    if (string.IsNullOrEmpty(alias))
                    {
                        // 如果没有,则使用导航属性别名
                        alias = _aliases.GetNavigationTableAlias(key);
                        if (!_navigations.ContainsKey(kvp.Key))
                        {
                            _navigations.Add(kvp);
                        }
                    }

                    if (stack.Count == 0 && !string.IsNullOrEmpty(memberName))
                    {
                        _builder.AppendMember(alias, memberName);
                    }
                }
            }
            else
            {
                // => SelectMany 也会产生类似 'b.Client.Address.AddressName' 这样的表达式
                string alias = _aliases.GetTableAlias(node);
                _builder.AppendMember(alias, memberName);
            }

            //return f;
        }
            // 添加导航属性关联
            protected virtual void AppendNavigation()
            {
                if (this.AdditionForeigns == null || this.AdditionForeigns.Count == 0)
                {
                    return;
                }

                //开始产生LEFT JOIN 子句
                SqlBuilder builder = this.JoinFragment;

                foreach (var kvp in _navigations)
                {
                    string           key          = kvp.Key;
                    MemberExpression m            = kvp.Value;
                    var runtime                   = TypeRuntimeInfoCache.GetRuntimeInfo(m.Expression.Type);
                    ForeignKeyAttribute attribute = runtime.GetWrapperAttribute <ForeignKeyAttribute>(m.Member.Name);

                    string innerKey   = string.Empty;
                    string outerKey   = key;
                    string innerAlias = string.Empty;

                    if (!m.Expression.IsVisitable())
                    {
                        innerKey = m.Expression.NodeType == ExpressionType.Parameter
                            ? (m.Expression as ParameterExpression).Name
                            : (m.Expression as MemberExpression).Member.Name;
                    }
                    else
                    {
                        MemberExpression mLeft = m.Expression as MemberExpression;
                        string           name  = TypeRuntimeInfoCache.GetRuntimeInfo(mLeft.Type).TableName;
                        innerAlias = _aliases.GetJoinTableAlias(name);

                        if (string.IsNullOrEmpty(innerAlias))
                        {
                            string keyLeft = mLeft.GetKeyWidthoutAnonymous();
                            if (_navigations.ContainsKey(keyLeft))
                            {
                                innerKey = keyLeft;
                            }
                        }
                    }

                    string alias1 = !string.IsNullOrEmpty(innerAlias) ? innerAlias : _aliases.GetTableAlias(innerKey);
                    string alias2 = _aliases.GetTableAlias(outerKey);


                    builder.AppendNewLine();
                    builder.Append("LEFT JOIN ");
                    Type pType = m.Type;
                    //不实现一对多映射
                    //if (pType.IsGenericType) pType = pType.GetGenericArguments()[0];
                    builder.AppendMember(TypeRuntimeInfoCache.GetRuntimeInfo(pType).TableName);
                    builder.Append(" ");
                    builder.Append(alias2);
                    builder.Append(" ON ");
                    for (int i = 0; i < attribute.InnerKeys.Length; i++)
                    {
                        builder.Append(alias1);
                        builder.Append('.');
                        builder.AppendMember(attribute.InnerKeys[i]);
                        builder.Append(" = ");
                        builder.Append(alias2);
                        builder.Append('.');
                        builder.AppendMember(attribute.OuterKeys[i]);

                        if (i < attribute.InnerKeys.Length - 1)
                        {
                            builder.Append(" AND ");
                        }
                    }
                }
            }