Esempio n. 1
0
 /// <summary>
 /// 实例化 <see cref="MethodCallExressionVisitor"/> 类的新实例
 /// </summary>
 public MethodCallExressionVisitor(IDbQueryProvider provider, ExpressionVisitorBase visitor)
 {
     _provider      = provider;
     _visitor       = visitor;
     _builder       = visitor.SqlBuilder;
     _visitedMember = _visitor.VisitedMember;
 }
Esempio n. 2
0
        /// <summary>
        /// 访问表示方法调用的节点
        /// </summary>
        /// <param name="node">方法调用节点</param>
        /// <param name="visitor">访问器</param>
        /// <returns></returns>
        public override Expression VisitMethodCall(MethodCallExpression node, ExpressionVisitorBase visitor)
        {
            Type   type       = node.Object != null ? node.Object.Type : node.Arguments[0].Type;
            string methodName = string.Empty;

            if (type == typeof(string) || node.Method.Name == "ToString")
            {
                methodName = "VisitStrMethodCall_";
            }
            else if (typeof(System.Collections.IEnumerable).IsAssignableFrom(type))
            {
                methodName = "VisitEnumMethodCall_";
            }

            if (!string.IsNullOrEmpty(methodName))
            {
                MemberAccess_Method invoker = null;
                MethodCallExressionVisitor._methods.TryGetValue(methodName + node.Method.Name, out invoker);
                if (invoker != null)
                {
                    object exp = invoker.Invoke(this, new object[] { node, visitor });
                    return(exp as Expression);
                }
            }

            throw new XfwException("{0}.{1} is not supported.", node.Method.DeclaringType, node.Method.Name);
        }
Esempio n. 3
0
        private Expression VisitStrMethodCall_SubString(MethodCallExpression m, ExpressionVisitorBase visitor)
        {
            if (m != null)
            {
                List <Expression> args = new List <Expression>(m.Arguments);
                if (m.Object != null)
                {
                    args.Insert(0, m.Object);
                }

                visitor.Append("SUBSTRING(");
                visitor.Visit(args[0]);
                visitor.Append(",");
                visitor.Visit(args[1]);
                visitor.Append(" + 1,");

                if (args.Count == 3)
                {
                    visitor.Visit(args[2]);
                }
                else
                {
                    visitor.Append("LEN(");
                    visitor.Visit(args[0]);
                    visitor.Append(")");
                }
                visitor.Append(")");
            }

            return(m);
        }
Esempio n. 4
0
        private Expression VisitStrMember_Length(MemberExpression m, ExpressionVisitorBase visitor)
        {
            visitor.Append("LEN(");
            visitor.Visit(m.Expression);
            visitor.Append(")");

            return(m);
        }
Esempio n. 5
0
 /// <summary>
 /// 实例化 <see cref="OracleMethodCallExressionVisitor"/> 类的新实例
 /// </summary>
 public OracleMethodCallExressionVisitor(IDbQueryProvider provider, ExpressionVisitorBase visitor)
     : base(provider, visitor)
 {
     _provider    = provider;
     _visitor     = visitor;
     _builder     = visitor.SqlBuilder;
     _visitedMark = _visitor.VisitedMark;
 }
Esempio n. 6
0
        private Expression VisitStrMethodCall_ToString(MethodCallExpression m, ExpressionVisitorBase visitor)
        {
            visitor.Append("CAST(");
            visitor.Visit(m.Object != null ? m.Object : m.Arguments[0]);
            visitor.Append(" AS VARCHAR)");

            return(m);
        }
Esempio n. 7
0
        // 创建 DELETE 命令
        protected override CommandDefine ParseDeleteCommand <T>(DbQueryableInfo_Delete <T> qDelete)
        {
            var        rInfo   = TypeRuntimeInfoCache.GetRuntimeInfo <T>();
            SqlBuilder builder = new SqlBuilder(this.EscCharLeft, this.EscCharRight);
            bool       useKey  = false;

            builder.Append("DELETE t0 FROM ");
            builder.AppendMember(rInfo.TableName);
            builder.Append(" t0 ");

            if (qDelete.Entity != null)
            {
                object entity = qDelete.Entity;

                builder.AppendNewLine();
                builder.Append("WHERE ");

                foreach (var kv in rInfo.Wrappers)
                {
                    var wrapper = kv.Value as MemberAccessWrapper;
                    var column  = wrapper.Column;

                    if (column != null && column.IsKey)
                    {
                        useKey = true;
                        var value = wrapper.Get(entity);
                        var seg   = ExpressionVisitorBase.GetSqlValue(value);
                        builder.AppendMember("t0", wrapper.Member.Name);
                        builder.Append(" = ");
                        builder.Append(seg);
                        builder.Append(" AND ");
                    }
                    ;
                }
                builder.Length -= 5;

                if (!useKey)
                {
                    throw new XfwException("Delete<T>(T value) require T must have key column.");
                }
            }
            else if (qDelete.SelectInfo != null)
            {
                TableAliasCache aliases = this.PrepareAlias <T>(qDelete.SelectInfo);
                var             sc      = new CommandDefine_Select.Builder(this.EscCharLeft, this.EscCharRight, aliases);

                ExpressionVisitorBase visitor = new JoinExpressionVisitor(this, aliases, qDelete.SelectInfo.Join);
                visitor.Write(sc.JoinFragment);

                visitor = new WhereExpressionVisitor(this, aliases, qDelete.SelectInfo.Where);
                visitor.Write(sc.WhereFragment);
                sc.AddNavigation(visitor.Navigations);

                builder.Append(sc.Command);
            }

            return(new CommandDefine(builder.ToString(), null, System.Data.CommandType.Text)); //builder.ToString();
        }
 /// <summary>
 /// 实例化 <see cref="SqlServerMethodCallExressionVisitor"/> 类的新实例
 /// </summary>
 /// <param name="provider">查询语义提供者</param>
 /// <param name="visitor">表达式访问器</param>
 public MySqlMethodCallExressionVisitor(IDbQueryProvider provider, ExpressionVisitorBase visitor)
     : base(provider, visitor)
 {
     _provider    = provider;
     _visitor     = visitor;
     _builder     = visitor.SqlBuilder;
     _visitedMark = _visitor.VisitedStack;
     _dbValue     = _provider.DbValue;
 }
Esempio n. 9
0
        private Expression VisitStrMethodCall_Trim(MethodCallExpression m, ExpressionVisitorBase visitor)
        {
            if (m != null)
            {
                visitor.Append("RTRIM(LTRIM(");
                visitor.Visit(m.Object != null ? m.Object : m.Arguments[0]);
                visitor.Append("))");
            }

            return(m);
        }
Esempio n. 10
0
        /// <summary>
        /// 访问表示 null 合并运算的节点 a ?? b
        /// </summary>
        /// <param name="b">二元表达式节点</param>
        /// <param name="visitor">访问器</param>
        /// <returns></returns>
        public override Expression VisitCoalesce(BinaryExpression b, ExpressionVisitorBase visitor)
        {
            // expression like a.Name ?? "TAN" => ISNULL(a.Name,'TAN')

            visitor.Append("ISNULL(");
            visitor.Visit(b.Left is ConstantExpression ? b.Right : b.Left);
            visitor.Append(",");
            visitor.Visit(b.Left is ConstantExpression ? b.Left : b.Right);
            visitor.Append(")");


            return(b);
        }
Esempio n. 11
0
        /// <summary>
        /// 访问表示 null 判断运算的节点 a.Name == null
        /// </summary>
        /// <param name="b">二元表达式节点</param>
        /// <param name="ExpressionVisitorBase">访问器</param>
        /// <returns></returns>
        public override Expression VisitEqualNull(BinaryExpression b, ExpressionVisitorBase visitor)
        {
            // a.Name == null => a.Name Is Null

            string oper = b.NodeType == ExpressionType.Equal
                ? " IS "
                : " IS NOT ";

            visitor.Visit(b.Left is ConstantExpression ? b.Right : b.Left);
            visitor.Append(oper);
            visitor.Visit(b.Left is ConstantExpression ? b.Left : b.Right);

            return(b);
        }
Esempio n. 12
0
        private Expression VisitEnumMethodCall_Contains(MethodCallExpression m, ExpressionVisitorBase visitor)
        {
            if (m == null)
            {
                return(m);
            }

            MemberExpression member = m.Arguments[m.Arguments.Count - 1] as MemberExpression;

            visitor.Visit(m.Arguments[m.Arguments.Count - 1]);
            visitor.Append(" IN(");

            //ConstantExpression constExpr = (m.Object != null ? m.Object : m.Arguments[0]) as ConstantExpression;
            //visitor.Visit(constExpr);
            Expression exp = m.Object != null ? m.Object : m.Arguments[0];

            if (exp.NodeType == ExpressionType.Constant)
            {
                visitor.Visit(exp);
            }
            else if (exp.NodeType == ExpressionType.MemberAccess)
            {
                visitor.Visit(exp.Evaluate());
            }
            else if (exp.NodeType == ExpressionType.NewArrayInit)
            {
                var expressions = (exp as NewArrayExpression).Expressions;
                for (int i = 0; i < expressions.Count; i++)
                {
                    visitor.Visit(expressions[i]);
                    if (i < expressions.Count - 1)
                    {
                        visitor.Append(",");
                    }
                }
            }

            visitor.Append(")");


            return(m);
        }
Esempio n. 13
0
        /// <summary>
        /// 访问表示字段或者属性的属性的节点 a.Name.Length
        /// </summary>
        /// <param name="node">字段或者属性节点</param>
        /// <param name="visitor">访问器</param>
        /// <returns></returns>
        public override Expression VisitMemberMember(MemberExpression node, ExpressionVisitorBase visitor)
        {
            Type   type       = node.Expression.Type;
            string methodName = string.Empty;

            if (type == typeof(string))
            {
                methodName = "VisitStrMember_";
            }

            if (!string.IsNullOrEmpty(methodName))
            {
                MemberAccess_Method invoker = null;
                MethodCallExressionVisitor._methods.TryGetValue(methodName + node.Member.Name, out invoker);
                if (invoker != null)
                {
                    object exp = invoker.Invoke(this, new object[] { node, visitor });
                    return(exp as Expression);
                }
            }

            throw new XfwException("{0}.{1} is not supported.", node.Member.DeclaringType, node.Member.Name);
        }
Esempio n. 14
0
        private Expression VisitStrMethodCall_EndsWith(MethodCallExpression m, ExpressionVisitorBase visitor)
        {
            if (m != null)
            {
                visitor.Visit(m.Object);
                visitor.Append(" LIKE ");
                if (m.Arguments[0].NodeType == ExpressionType.Constant)
                {
                    ConstantExpression c = m.Arguments[0] as ConstantExpression;
                    //visitor.Append(string.Format("N'%{0}'", c.Value));
                    visitor.Append("N'%");
                    visitor.Append(c.Value != null ? c.Value.ToString() : string.Empty);
                    visitor.Append("'");
                }
                else
                {
                    visitor.Append("('%' + ");
                    visitor.Visit(m.Arguments[0]);
                    visitor.Append(")");
                }
            }

            return(m);
        }
        /// <summary>
        /// 创建 UPDATE 命令
        /// </summary>
        /// <param name="dbQuery">查询语义</param>
        /// <param name="token">解析上下文</param>
        /// <returns></returns>
        protected override RawCommand ResolveUpdateCommand <T>(IDbQueryableInfo_Update dbQuery, ResolveToken token)
        {
            var         context     = (SqlServerDbContext)token.DbContext;
            ISqlBuilder builder     = this.CreateSqlBuilder(token);
            var         typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            builder.Append("UPDATE t0 SET");
            builder.AppendNewLine();

            if (dbQuery.Entity != null)
            {
                object      entity    = dbQuery.Entity;
                ISqlBuilder seg_Where = this.CreateSqlBuilder(token);
                bool        useKey    = false;
                int         length    = 0;

                foreach (var m in typeRuntime.Members)
                {
                    var column = m.Column;
                    if (column != null && column.IsIdentity)
                    {
                        goto gotoLabel;                                      // Fix issue# 自增列同时又是主键
                    }
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (m.Column != null && column.DbType is SqlDbType && (SqlDbType)column.DbType == SqlDbType.Timestamp)
                    {
                        continue;                                                                                                    // 行版本号
                    }
                    if (m.ForeignKey != null)
                    {
                        continue;
                    }
                    if (m.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

                    builder.AppendMember("t0", m.Member.Name);
                    builder.Append(" = ");

gotoLabel:
                    var value = m.Invoke(entity);
                    var seg = this.DbValue.GetSqlValueWidthDefault(value, token, column);

                    if (column == null || !column.IsIdentity)
                    {
                        builder.Append(seg);
                        length = builder.Length;
                        builder.Append(',');
                        builder.AppendNewLine();
                    }

                    if (column != null && column.IsKey)
                    {
                        useKey = true;
                        seg_Where.AppendMember("t0", m.Member.Name);
                        seg_Where.Append(" = ");
                        seg_Where.Append(seg);
                        seg_Where.Append(" AND ");
                    }
                }

                if (!useKey)
                {
                    throw new XFrameworkException("Update<T>(T value) require entity must have key column.");
                }

                builder.Length    = length;
                seg_Where.Length -= 5;

                builder.AppendNewLine();
                builder.Append("FROM ");
                builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                builder.Append(" t0");

                builder.AppendNewLine();
                builder.Append("WHERE ");
                builder.Append(seg_Where);
            }
            else if (dbQuery.Expression != null)
            {
                TableAlias            aliases = this.PrepareTableAlias(dbQuery.Query, token);
                ExpressionVisitorBase visitor = null;
                visitor = new UpdateExpressionVisitor(this, aliases, dbQuery.Expression);
                visitor.Write(builder);

                builder.AppendNewLine();
                builder.Append("FROM ");
                builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                builder.AppendAs("t0");

                var cmd = new SqlServerMappingCommand(context, aliases, token)
                {
                    HasMany = dbQuery.Query.HasMany
                };

                visitor = new SqlServerJoinExpressionVisitor(context, aliases, dbQuery.Query.Joins);
                visitor.Write(cmd.JoinFragment);

                visitor = new WhereExpressionVisitor(this, aliases, dbQuery.Query.Where);
                visitor.Write(cmd.WhereFragment);
                cmd.AddNavMembers(visitor.NavMembers);

                builder.Append(cmd.CommandText);
            }

            return(new RawCommand(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
Esempio n. 16
0
        // 创建 UPDATE 命令
        protected override DbCommandDefinition ParseUpdateCommand <T>(DbQueryableInfo_Update <T> uQuery, List <IDbDataParameter> parameters = null)
        {
            ISqlBuilder builder     = this.CreateSqlBuilder(parameters);
            var         typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            builder.Append("UPDATE ");
            builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
            builder.Append(" t0 SET");
            builder.AppendNewLine();

            if (uQuery.Entity != null)
            {
                object      entity       = uQuery.Entity;
                ISqlBuilder whereBuilder = this.CreateSqlBuilder(builder.Parameters);
                bool        useKey       = false;
                int         length       = 0;


                foreach (var kv in typeRuntime.Invokers)
                {
                    MemberInvokerBase invoker = kv.Value;
                    var column = invoker.Column;
                    if (column != null && column.IsIdentity)
                    {
                        goto gotoLabel;                                      // fix issue# 自增列同时又是主键
                    }
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (invoker.ForeignKey != null)
                    {
                        continue;
                    }
                    if (invoker.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

                    builder.AppendMember(invoker.Member.Name);
                    builder.Append(" = ");

gotoLabel:

                    if (column == null || !column.IsIdentity)
                    {
                        var value = invoker.Invoke(entity);
                        var seg   = builder.GetSqlValueWidthDefault(value, column);

                        builder.Append(seg);
                        length = builder.Length;
                        builder.Append(',');
                        builder.AppendNewLine();
                    }

                    if (column != null && column.IsKey)
                    {
                        useKey = true;
                    }
                }

                if (!useKey)
                {
                    throw new XFrameworkException("Update<T>(T value) require T must have key column.");
                }


                // ORACLE 需要注意参数顺序问题
                int index = -1;
                foreach (var kv in typeRuntime.KeyInvokers)
                {
                    MemberInvokerBase invoker = kv.Value;
                    var column = invoker.Column;
                    var value  = invoker.Invoke(entity);
                    var seg    = builder.GetSqlValueWidthDefault(value, column);
                    index += 1;

                    whereBuilder.AppendMember(invoker.Member.Name);
                    whereBuilder.Append(" = ");
                    whereBuilder.Append(seg);
                    if (index < typeRuntime.KeyInvokers.Count - 1)
                    {
                        whereBuilder.Append(" AND ");
                    }
                }

                builder.Length = length;
                builder.AppendNewLine();
                builder.Append("WHERE ");
                builder.Append(whereBuilder);
            }
            else if (uQuery.Expression != null)
            {
                TableAliasCache       aliases = this.PrepareAlias <T>(uQuery.SelectInfo);
                ExpressionVisitorBase visitor = null;
                visitor = new OracleUpdateExpressionVisitor(this, aliases, uQuery.Expression);
                visitor.Write(builder);

                var cmd2 = new OracleDbCommandDefinition_Delete(this, aliases, builder.Parameters);
                cmd2.HaveListNavigation = uQuery.SelectInfo.HaveListNavigation;

                var visitor0 = new OracleJoinExpressionVisitor(this, aliases, uQuery.SelectInfo.Join, uQuery.SelectInfo.Where);
                visitor0.Write(cmd2);

                var visitor1 = new OracleWhereExpressionVisitor(this, aliases, uQuery.SelectInfo.Where);
                visitor1.Write(cmd2.WhereFragment);
                cmd2.AddNavMembers(visitor1.NavMembers);
                builder.Append(cmd2.CommandText);
            }

            builder.Append(';');
            return(new DbCommandDefinition(builder.ToString(), builder.Parameters, System.Data.CommandType.Text));
        }
Esempio n. 17
0
 /// <summary>
 /// 创建方法表达式访问器
 /// </summary>
 /// <returns></returns>
 public override IMethodCallExressionVisitor CreateMethodCallVisitor(ExpressionVisitorBase visitor)
 {
     return(new OracleMethodCallExressionVisitor(this, visitor));
 }
Esempio n. 18
0
 /// <summary>
 /// 实例化 <see cref="SqlMethodCallExressionVisitor"/> 类的新实例
 /// </summary>
 public SqlMethodCallExressionVisitor(IDbQueryProvider provider, ExpressionVisitorBase visitor)
     : base(provider, visitor)
 {
 }
 protected override IMappingObjectExpression VisitLambda(LambdaExpression exp)
 {
     this._lambda  = exp;
     this._visitor = new GeneralExpressionVisitor(exp, this._moeList);
     return(this.Visit(exp.Body));
 }
Esempio n. 20
0
        // 创建 UPDATE 命令
        protected override Command ResolveUpdateCommand <T>(DbQueryableInfo_Update <T> dbQuery, ResolveToken token)
        {
            ISqlBuilder builder     = this.CreateSqlBuilder(token);
            var         typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            builder.Append("UPDATE ");
            builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
            builder.Append(" t0 SET");
            builder.AppendNewLine();

            if (dbQuery.Entity != null)
            {
                object      entity       = dbQuery.Entity;
                ISqlBuilder whereBuilder = this.CreateSqlBuilder(token);
                bool        useKey       = false;
                int         length       = 0;

                foreach (var invoker in typeRuntime.Invokers)
                {
                    var column = invoker.Column;
                    if (column != null && column.IsIdentity)
                    {
                        goto gotoLabel;                                      // fix issue# 自增列同时又是主键
                    }
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (invoker.ForeignKey != null)
                    {
                        continue;
                    }
                    if (invoker.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

                    builder.AppendMember(invoker.Member.Name);
                    builder.Append(" = ");

gotoLabel:
                    var value = invoker.Invoke(entity);
                    var seg = this.DbValue.GetSqlValueWidthDefault(value, token, column);

                    if (column == null || !column.IsIdentity)
                    {
                        builder.Append(seg);
                        length = builder.Length;
                        builder.Append(',');
                        builder.AppendNewLine();
                    }

                    if (column != null && column.IsKey)
                    {
                        useKey = true;
                        whereBuilder.AppendMember(invoker.Member.Name);
                        whereBuilder.Append(" = ");
                        whereBuilder.Append(seg);
                        whereBuilder.Append(" AND ");
                    }
                }

                if (!useKey)
                {
                    throw new XFrameworkException("Update<T>(T value) require T must have key column.");
                }

                builder.Length       = length;
                whereBuilder.Length -= 5;

                builder.AppendNewLine();
                builder.Append("WHERE ");
                builder.Append(whereBuilder);
            }
            else if (dbQuery.Expression != null)
            {
                TableAliasCache       aliases = this.PrepareTableAlias <T>(dbQuery.SelectInfo, token);
                ExpressionVisitorBase visitor = null;
                visitor = new NpgUpdateExpressionVisitor(this, aliases, dbQuery.Expression);
                visitor.Write(builder);

                var cmd2 = new NpgMapperCommand(this, aliases, DbExpressionType.Update, token)
                {
                    HasMany = dbQuery.SelectInfo.HasMany
                };

                var visitor0 = new NpgJoinExpressionVisitor(this, aliases, dbQuery.SelectInfo.Joins, DbExpressionType.Update);
                visitor0.Write(cmd2);

                var visitor1 = new NpgWhereExpressionVisitor(this, aliases, dbQuery.SelectInfo.Condtion);
                visitor1.Write(cmd2.WhereFragment);
                cmd2.AddNavMembers(visitor1.NavMembers);
                builder.Append(cmd2.CommandText);
            }

            builder.Append(';');
            return(new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
Esempio n. 21
0
 protected override IMappingObjectExpression VisitLambda(LambdaExpression exp)
 {
     this._visitor = new GeneralExpressionParser(this._scopeParameters, this._scopeTables);
     return(this.Visit(exp.Body));
 }
Esempio n. 22
0
        // 创建 UPDATE 命令
        protected override Command ResolveUpdateCommand <T>(DbQueryableInfo_Update <T> dbQuery, ResolveToken token)
        {
            ISqlBuilder builder     = this.CreateSqlBuilder(token);
            var         typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            builder.Append("UPDATE ");
            builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
            builder.Append(" t0 SET");
            builder.AppendNewLine();

            if (dbQuery.Entity != null)
            {
                object      entity       = dbQuery.Entity;
                ISqlBuilder whereBuilder = this.CreateSqlBuilder(token);
                bool        useKey       = false;
                int         length       = 0;


                foreach (var invoker in typeRuntime.Invokers)
                {
                    var column = invoker.Column;
                    if (column != null && column.IsIdentity)
                    {
                        goto gotoLabel;                                      // fix issue# 自增列同时又是主键
                    }
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (invoker.ForeignKey != null)
                    {
                        continue;
                    }
                    if (invoker.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

                    builder.AppendMember(invoker.Member.Name);
                    builder.Append(" = ");

gotoLabel:

                    if (column == null || !column.IsIdentity)
                    {
                        var value = invoker.Invoke(entity);
                        var seg   = this.DbValue.GetSqlValueWidthDefault(value, token, column);

                        builder.Append(seg);
                        length = builder.Length;
                        builder.Append(',');
                        builder.AppendNewLine();
                    }

                    if (column != null && column.IsKey)
                    {
                        useKey = true;
                    }
                }

                if (!useKey)
                {
                    throw new XFrameworkException("Update<T>(T value) require T must have key column.");
                }


                // ORACLE 需要注意参数顺序问题
                int index = -1;
                foreach (var invoker in typeRuntime.KeyInvokers)
                {
                    var column = invoker.Column;
                    var value  = invoker.Invoke(entity);
                    var seg    = this.DbValue.GetSqlValueWidthDefault(value, token, column);
                    index += 1;

                    whereBuilder.AppendMember(invoker.Member.Name);
                    whereBuilder.Append(" = ");
                    whereBuilder.Append(seg);
                    if (index < typeRuntime.KeyInvokers.Count - 1)
                    {
                        whereBuilder.Append(" AND ");
                    }
                }

                builder.Length = length;
                builder.AppendNewLine();
                builder.Append("WHERE ");
                builder.Append(whereBuilder);
            }
            else if (dbQuery.Expression != null)
            {
                // SELECT 表达式
                LambdaExpression lambda = dbQuery.Expression as LambdaExpression;
                var        body         = lambda.Body;
                Expression expression   = null;
                if (body.NodeType == ExpressionType.MemberInit)
                {
                    var memberInit = body as MemberInitExpression;
                    var bindings   = new List <MemberBinding>(memberInit.Bindings);
                    foreach (var invoker in typeRuntime.KeyInvokers)
                    {
                        var member  = Expression.MakeMemberAccess(lambda.Parameters[0], invoker.Member);
                        var binding = Expression.Bind(invoker.Member, member);
                        if (!bindings.Any(x => x.Member == invoker.Member))
                        {
                            bindings.Add(binding);
                        }
                    }
                    expression = Expression.MemberInit(memberInit.NewExpression, bindings);
                }
                else if (body.NodeType == ExpressionType.New)
                {
                    var newExpression = body as NewExpression;
                    var bindings      = new List <MemberBinding>();
                    for (int i = 0; i < newExpression.Members.Count; i++)
                    {
                        var invoker = typeRuntime.GetInvoker(newExpression.Members[i].Name);
                        var binding = Expression.Bind(invoker.Member, newExpression.Arguments[i].Type != invoker.DataType
                            ? Expression.Convert(newExpression.Arguments[i], invoker.DataType)
                            : newExpression.Arguments[i]);
                        bindings.Add(binding);
                    }

                    foreach (var invoker in typeRuntime.KeyInvokers)
                    {
                        var member  = Expression.MakeMemberAccess(lambda.Parameters[0], invoker.Member);
                        var binding = Expression.Bind(invoker.Member, member);
                        if (!bindings.Any(x => x.Member == invoker.Member))
                        {
                            bindings.Add(binding);
                        }
                    }

                    var newExpression2 = Expression.New(typeRuntime.ConstructInvoker.Constructor);
                    expression = Expression.MemberInit(newExpression2, bindings);
                }

                // 解析查询以确定是否需要嵌套
                dbQuery.SelectInfo.Select = new DbExpression(DbExpressionType.Select, expression);
                var cmd = (MapperCommand)this.ResolveSelectCommand <T>(dbQuery.SelectInfo, 1, false, null);//, token);

                if ((cmd.NavMembers != null && cmd.NavMembers.Count > 0) || dbQuery.SelectInfo.Joins.Count > 0)
                {
                    // 无法使用 DISTINCT, GROUP BY 等子句从视图中选择 ROWID 或采样。UPDATE 不能用rowid
                    // 有导航属性或者关联查询,使用 MERGE INTO 语法。要求必须有主键

                    if (typeRuntime.KeyInvokers == null || typeRuntime.KeyInvokers.Count == 0)
                    {
                        throw new XFrameworkException("Update<T>(Expression<Func<T, object>> updateExpression) require entity must have key column.");
                    }

                    builder.Length = 0;
                    builder.Append("MERGE INTO ");
                    builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                    builder.AppendNewLine(" t0");
                    builder.Append("USING (");

                    cmd = (MapperCommand)this.ResolveSelectCommand <T>(dbQuery.SelectInfo, 1, false, token);
                    builder.AppendNewLine(cmd.CommandText);
                    builder.Append(") t1 ON (");
                    foreach (var invoker in typeRuntime.KeyInvokers)
                    {
                        builder.AppendMember("t0", invoker.Name);
                        builder.Append(" = ");
                        builder.AppendMember("t1", invoker.Name);
                        builder.Append(" AND ");
                    }
                    builder.Length -= 5;
                    builder.Append(')');

                    // UPDATE
                    builder.AppendNewLine();
                    builder.AppendNewLine("WHEN MATCHED THEN UPDATE SET ");

                    // SET 字段
                    var visitor = new OracleUpdateExpressionVisitor(this, null, dbQuery.Expression);
                    visitor.Write(builder);
                }
                else
                {
                    // 直接 SQL 的 UPDATE 语法
                    TableAliasCache       aliases = this.PrepareTableAlias <T>(dbQuery.SelectInfo, token);
                    ExpressionVisitorBase visitor = null;
                    visitor = new UpdateExpressionVisitor(this, aliases, dbQuery.Expression);
                    visitor.Write(builder);

                    visitor = new WhereExpressionVisitor(this, aliases, dbQuery.SelectInfo.Condtion);
                    visitor.Write(builder);
                }
            }

            builder.Append(';');
            return(new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
Esempio n. 23
0
        // 创建 DELETE 命令
        protected override Command ParseDeleteCommand <T>(DbQueryableInfo_Delete <T> dQueryInfo, ResolveToken token)
        {
            ISqlBuilder     builder     = this.CreateSqlBuilder(token);
            TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            builder.Append("DELETE FROM ");
            builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
            builder.Append(" ");

            if (dQueryInfo.Entity != null)
            {
                if (typeRuntime.KeyInvokers == null || typeRuntime.KeyInvokers.Count == 0)
                {
                    throw new XFrameworkException("Delete<T>(T value) require entity must have key column.");
                }

                object entity = dQueryInfo.Entity;

                builder.AppendNewLine();
                builder.Append("WHERE ");

                foreach (var invoker in typeRuntime.KeyInvokers)
                {
                    var column = invoker.Column;
                    var value  = invoker.Invoke(entity);
                    var seg    = this.DbValue.GetSqlValue(value, token, column);

                    builder.AppendMember(invoker.Member.Name);
                    builder.Append(" = ");
                    builder.Append(seg);
                    builder.Append(" AND ");
                }
                builder.Length -= 5;
            }
            else if (dQueryInfo.SelectInfo != null)
            {
                LambdaExpression lambda = null;
                var dbQuery             = dQueryInfo.SourceQuery;
                if (dbQuery.DbExpressions != null && dbQuery.DbExpressions.Count > 1)
                {
                    switch (dbQuery.DbExpressions[1].DbExpressionType)
                    {
                    case DbExpressionType.Join:
                    case DbExpressionType.GroupJoin:
                    case DbExpressionType.GroupRightJoin:
                        lambda = (LambdaExpression)dbQuery.DbExpressions[1].Expressions[1];
                        break;

                    case DbExpressionType.Select:
                    case DbExpressionType.SelectMany:
                        lambda = (LambdaExpression)dbQuery.DbExpressions[1].Expressions[0];
                        break;
                    }
                }
                if (lambda == null)
                {
                    DbExpression dbExpression = dQueryInfo.SelectInfo.SelectExpression;
                    dbExpression = dQueryInfo.SelectInfo.WhereExpression;
                    if (dbExpression != null && dbExpression.Expressions != null)
                    {
                        lambda = (LambdaExpression)dbExpression.Expressions[0];
                    }
                }

                // 解析查询以确定是否需要嵌套
                var parameter  = Expression.Parameter(typeof(SQLiteRowId), lambda != null ? lambda.Parameters[0].Name : "x");
                var expression = Expression.MakeMemberAccess(parameter, (_rowIdExpression.Body as MemberExpression).Member);
                dQueryInfo.SelectInfo.SelectExpression = new DbExpression(DbExpressionType.Select, expression);
                var cmd = (MappingCommand)this.ParseSelectCommand <T>(dQueryInfo.SelectInfo, 1, false, null);
                if (token != null && token.Extendsions == null)
                {
                    token.Extendsions = new Dictionary <string, object>();
                    if (!token.Extendsions.ContainsKey("SQLiteDelete"))
                    {
                        token.Extendsions.Add("SQLiteDelete", null);
                    }
                }

                if ((cmd.NavMembers != null && cmd.NavMembers.Count > 0) || dQueryInfo.SelectInfo.Joins.Count > 0)
                {
                    cmd = (MappingCommand)this.ParseSelectCommand <T>(dQueryInfo.SelectInfo, 1, false, token);
                    builder.Append("WHERE ");
                    builder.AppendMember("RowID");
                    builder.Append(" IN(");
                    builder.AppendNewLine(cmd.CommandText);
                    builder.Append(')');
                }
                else
                {
                    TableAliasCache       aliases = this.PrepareAlias <T>(dQueryInfo.SelectInfo, token);
                    ExpressionVisitorBase visitor = null;

                    visitor = new JoinExpressionVisitor(this, aliases, dQueryInfo.SelectInfo.Joins);
                    visitor.Write(builder);

                    visitor = new WhereExpressionVisitor(this, null, dQueryInfo.SelectInfo.WhereExpression);
                    visitor.Write(builder);
                }
            }

            builder.Append(';');
            return(new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
Esempio n. 24
0
        // 创建 INSRT 命令
        protected override CommandDefine ParseInsertCommand <T>(DbQueryableInfo_Insert <T> qInsert)
        {
            SqlBuilder      builder = new SqlBuilder(this.EscCharLeft, this.EscCharRight);
            var             rInfo   = TypeRuntimeInfoCache.GetRuntimeInfo <T>();
            TableAliasCache aliases = new TableAliasCache();

            if (qInsert.Entity != null)
            {
                object     entity  = qInsert.Entity;
                SqlBuilder columns = new SqlBuilder(this.EscCharLeft, this.EscCharRight);
                SqlBuilder values  = new SqlBuilder(this.EscCharLeft, this.EscCharRight);

                foreach (var kv in rInfo.Wrappers)
                {
                    var wrapper = kv.Value as MemberAccessWrapper;
                    var column  = wrapper.Column;
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (wrapper.ForeignKey != null)
                    {
                        continue;
                    }

                    if (wrapper != qInsert.AutoIncrement)
                    {
                        columns.AppendMember(wrapper.Member.Name);
                        columns.Append(',');

                        var    value = wrapper.Get(entity);
                        string seg   = ExpressionVisitorBase.GetSqlValue(value);
                        values.Append(seg);
                        values.Append(',');
                    }
                }
                columns.Length -= 1;
                values.Length  -= 1;

                if (qInsert.Bulk == null || !qInsert.Bulk.OnlyValue)
                {
                    builder.Append("INSERT INTO ");
                    builder.AppendMember(rInfo.TableName);
                    builder.AppendNewLine();
                    builder.Append('(');
                    builder.Append(columns);
                    builder.Append(')');
                    builder.AppendNewLine();
                    builder.Append("VALUES");
                    builder.AppendNewLine();
                }

                builder.Append('(');
                builder.Append(values);
                builder.Append(')');
                if (qInsert.Bulk != null && !qInsert.Bulk.IsOver)
                {
                    builder.Append(",");
                }

                if (qInsert.Bulk == null && qInsert.AutoIncrement != null)
                {
                    builder.AppendNewLine();
                    builder.Append("SELECT CAST(SCOPE_IDENTITY() AS INT)");
                }
            }
            else if (qInsert.SelectInfo != null)
            {
                builder.Append("INSERT INTO ");
                builder.AppendMember(rInfo.TableName);
                builder.Append('(');

                CommandDefine_Select sc = this.ParseSelectCommand(qInsert.SelectInfo) as CommandDefine_Select;
                //for (int i = 0; i < seg.Columns.Count; i++)
                int i = 0;
                foreach (var kvp in sc.Columns)
                {
                    builder.AppendMember(kvp.Key);
                    if (i < sc.Columns.Count - 1)
                    {
                        builder.Append(',');
                        builder.AppendNewLine();
                    }

                    i++;
                }

                builder.Append(')');
                builder.AppendNewLine();
                builder.Append(sc.CommandText);
            }

            return(new CommandDefine(builder.ToString(), null, System.Data.CommandType.Text)); //builder.ToString();
        }
Esempio n. 25
0
        /// <summary>
        /// 创建 DELETE 命令
        /// </summary>
        /// <param name="dbQuery">查询语义</param>
        /// <param name="token">解析上下文</param>
        /// <returns></returns>
        protected override RawCommand ResolveDeleteCommand <T>(IDbQueryableInfo_Delete dbQuery, ResolveToken token)
        {
            ISqlBuilder builder     = this.CreateSqlBuilder(token);
            var         typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            builder.Append("DELETE FROM ");
            builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
            builder.Append(" ");

            if (dbQuery.Entity != null)
            {
                if (typeRuntime.KeyMembers == null || typeRuntime.KeyMembers.Count == 0)
                {
                    throw new XFrameworkException("Delete<T>(T value) require entity must have key column.");
                }

                object entity = dbQuery.Entity;

                builder.AppendNewLine();
                builder.Append("WHERE ");

                foreach (var m in typeRuntime.KeyMembers)
                {
                    var column = m.Column;
                    var value  = m.Invoke(entity);
                    var seg    = this.DbValue.GetSqlValue(value, token, column);

                    builder.AppendMember(m.Member.Name);
                    builder.Append(" = ");
                    builder.Append(seg);
                    builder.Append(" AND ");
                }
                builder.Length -= 5;
            }
            else if (dbQuery.Query != null)
            {
                // 解析查询用来确定是否需要嵌套
                var cmd = this.ResolveSelectCommand(dbQuery.Query, 1, false, null) as MappingCommand;
                if (token != null && token.Extendsions == null)
                {
                    token.Extendsions = new Dictionary <string, object>();
                    if (!token.Extendsions.ContainsKey("SQLiteDelete"))
                    {
                        token.Extendsions.Add("SQLiteDelete", null);
                    }
                }

                if ((cmd.NavMembers != null && cmd.NavMembers.Count > 0) || dbQuery.Query.Joins.Count > 0)
                {
                    // 最外层仅选择 RowID 列
                    var outQuery = dbQuery.Query;
                    outQuery.Select = new DbExpression(DbExpressionType.Select, Expression.Constant("t0.RowId", typeof(string)));
                    var iterator = outQuery;
                    while (iterator.Subquery != null)
                    {
                        var subQuery = new SQLiteDbQueryableInfo_Select(iterator.Subquery);
                        iterator.Subquery = subQuery;
                        iterator          = subQuery;
                    }

                    // 解析成 RowId IN 结构
                    cmd = (MappingCommand)this.ResolveSelectCommand(dbQuery.Query, 1, false, token);
                    builder.Append("WHERE ");
                    builder.AppendMember("RowID");
                    builder.Append(" IN(");
                    builder.AppendNewLine(cmd.CommandText);
                    builder.Append(')');
                }
                else
                {
                    TableAlias            aliases = this.PrepareTableAlias(dbQuery.Query, token);
                    ExpressionVisitorBase visitor = null;

                    visitor = new JoinExpressionVisitor(this, aliases, dbQuery.Query.Joins);
                    visitor.Write(builder);

                    visitor = new WhereExpressionVisitor(this, null, dbQuery.Query.Where);
                    visitor.Write(builder);
                }
            }

            builder.Append(';');
            return(new RawCommand(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
Esempio n. 26
0
        // 创建 UPDATE 命令
        protected override Command ParseUpdateCommand <T>(DbQueryableInfo_Update <T> uQueryInfo, ParserToken token)
        {
            ISqlBuilder builder     = this.CreateSqlBuilder(token);
            var         typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            builder.Append("UPDATE t0 SET");
            builder.AppendNewLine();

            if (uQueryInfo.Entity != null)
            {
                object      entity       = uQueryInfo.Entity;
                ISqlBuilder whereBuilder = this.CreateSqlBuilder(token);
                bool        useKey       = false;
                int         length       = 0;

                foreach (var kv in typeRuntime.Invokers)
                {
                    MemberInvokerBase invoker = kv.Value;
                    var column = invoker.Column;
                    if (column != null && column.IsIdentity)
                    {
                        goto gotoLabel;                                      // fix issue# 自增列同时又是主键
                    }
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (invoker.Column != null && column.DbType is SqlDbType && (SqlDbType)column.DbType == SqlDbType.Timestamp)
                    {
                        continue;                                                                                                          // 行版本号
                    }
                    if (invoker.ForeignKey != null)
                    {
                        continue;
                    }
                    if (invoker.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

                    builder.AppendMember("t0", invoker.Member.Name);
                    builder.Append(" = ");

gotoLabel:
                    var value = invoker.Invoke(entity);
                    var seg = builder.GetSqlValueWidthDefault(value, column);

                    if (column == null || !column.IsIdentity)
                    {
                        builder.Append(seg);
                        length = builder.Length;
                        builder.Append(',');
                        builder.AppendNewLine();
                    }

                    if (column != null && column.IsKey)
                    {
                        useKey = true;
                        whereBuilder.AppendMember("t0", invoker.Member.Name);
                        whereBuilder.Append(" = ");
                        whereBuilder.Append(seg);
                        whereBuilder.Append(" AND ");
                    }
                }

                if (!useKey)
                {
                    throw new XFrameworkException("Update<T>(T value) require T must have key column.");
                }

                builder.Length       = length;
                whereBuilder.Length -= 5;

                builder.AppendNewLine();
                builder.Append("FROM ");
                builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                builder.Append(" t0");


                builder.AppendNewLine();
                builder.Append("WHERE ");
                builder.Append(whereBuilder);
            }
            else if (uQueryInfo.Expression != null)
            {
                TableAliasCache       aliases = this.PrepareAlias <T>(uQueryInfo.SelectInfo, token);
                ExpressionVisitorBase visitor = null;
                visitor = new UpdateExpressionVisitor(this, aliases, uQueryInfo.Expression);
                visitor.Write(builder);

                builder.AppendNewLine();
                builder.Append("FROM ");
                builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                builder.AppendAs("t0");

                var cmd2 = new SelectCommand(this, aliases, token)
                {
                    HasManyNavigation = uQueryInfo.SelectInfo.HasManyNavigation
                };

                visitor = new JoinExpressionVisitor(this, aliases, uQueryInfo.SelectInfo.Joins);
                visitor.Write(cmd2.JoinFragment);

                visitor = new WhereExpressionVisitor(this, aliases, uQueryInfo.SelectInfo.WhereExpression);
                visitor.Write(cmd2.WhereFragment);
                cmd2.AddNavMembers(visitor.NavMembers);

                builder.Append(cmd2.CommandText);
            }

            return(new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
Esempio n. 27
0
 /// <summary>
 /// 创建方法表达式访问器
 /// </summary>
 /// <param name="visitor">表达式访问器</param>
 /// <returns></returns>
 public override MethodCallExpressionVisitor CreateMethodVisitor(ExpressionVisitorBase visitor)
 {
     return(new SQLiteMethodCallExressionVisitor(this, visitor));
 }
Esempio n. 28
0
        // 创建 SELECT 命令
        protected override CommandDefine ParseSelectCommand <T>(DbQueryableInfo_Select <T> qQuery, int indent = 0)
        {
            // 说明:
            // 1.OFFSET 前必须要有 'ORDER BY',即 'Skip' 子句前必须使用 'OrderBy' 子句
            // 2.在有统计函数的<MAX,MIN...>情况下,如果有 'Distinct' 'GroupBy' 'Skip' 'Take' 子句,则需要使用嵌套查询
            // 3.'Any' 子句将翻译成 IF EXISTS...
            // 4.分组再分页时需要使用嵌套查询,此时子查询不需要 'OrderBy' 子句,但最外层则需要
            // 5.'Skip' 'Take' 子句视为语义结束符,在其之后的子句将使用嵌套查询

            bool willNest      = qQuery.HaveDistinct || qQuery.GroupBy != null || qQuery.Skip > 0 || qQuery.Take > 0;
            bool useStatis     = qQuery.Statis != null;
            bool groupByPaging = qQuery.GroupBy != null && qQuery.Skip > 0;          // 分组分页
            bool useOrderBy    = (!useStatis || qQuery.Skip > 0) && !qQuery.HaveAny; // 没有统计函数或者使用 'Skip' 子句,则解析OrderBy

            ExpressionVisitorBase visitor = null;
            TableAliasCache       aliases = this.PrepareAlias <T>(qQuery);
            string statName = string.Empty;

            CommandDefine_Select sc = new CommandDefine_Select(this.EscCharLeft, this.EscCharRight, aliases);
            SqlBuilder           jf = sc.JoinFragment;
            SqlBuilder           wf = sc.WhereFragment;

            if (groupByPaging)
            {
                indent = indent + 1;
            }
            jf.Indent = indent;

            #region 嵌套查询

            if (useStatis && willNest)
            {
                // SELECT
                jf.Append("SELECT ");
                jf.AppendNewLine();

                // SELECT COUNT(1)
                visitor = new StatisExpressionVisitor(this, aliases, qQuery.Statis, qQuery.GroupBy, "t0");
                visitor.Write(jf);
                statName = (visitor as StatisExpressionVisitor).ColumnName;
                sc.AddNavigation(visitor.Navigations);

                // SELECT COUNT(1) FROM
                jf.AppendNewLine();
                jf.Append("FROM ( ");

                indent   += 1;
                jf.Indent = indent;
            }

            #endregion

            // SELECT 子句
            if (jf.Indent > 0)
            {
                jf.AppendNewLine();
            }

            if (qQuery.HaveAny)
            {
                jf.Append("IF EXISTS(");
                indent   += 1;
                jf.Indent = indent;
                jf.AppendNewLine();
            }

            jf.Append("SELECT ");

            if (useStatis && !willNest)
            {
                // 如果有统计函数,并且不是嵌套的话,则直接使用SELECT <MAX,MIN...>,不需要解析选择的字段
                jf.AppendNewLine();
                visitor = new StatisExpressionVisitor(this, aliases, qQuery.Statis, qQuery.GroupBy);
                visitor.Write(jf);
                sc.AddNavigation(visitor.Navigations);
            }
            else
            {
                // DISTINCT 子句
                if (qQuery.HaveDistinct)
                {
                    jf.Append("DISTINCT ");
                }

                // TOP 子句
                if (qQuery.Take > 0 && qQuery.Skip == 0)
                {
                    jf.AppendFormat("TOP({0})", qQuery.Take);
                }

                // Any
                if (qQuery.HaveAny)
                {
                    jf.Append("TOP 1 1");
                }

                #region  择字段

                if (!qQuery.HaveAny)
                {
                    // SELECT 范围
                    visitor = new ColumnExpressionVisitor(this, aliases, qQuery.Expression, qQuery.GroupBy);
                    visitor.Write(jf);

                    sc.Columns        = (visitor as ColumnExpressionVisitor).Columns;
                    sc.NavDescriptors = (visitor as ColumnExpressionVisitor).NavDescriptors;
                    sc.AddNavigation(visitor.Navigations);

                    // 如果有统计,选择列中还要追加统计的列
                    if (useStatis && willNest)
                    {
                        string columnName = statName;
                        if (!string.IsNullOrEmpty(columnName) && !sc.Columns.ContainsKey(columnName))
                        {
                            if (sc.Columns.Count > 0)
                            {
                                jf.Append(",");
                            }
                            visitor = new ColumnExpressionVisitor(this, aliases, qQuery.Statis, qQuery.GroupBy, true);
                            visitor.Write(jf);

                            sc.Columns.Add(columnName, new Column {
                                Name = columnName, Duplicate = 1
                            });
                            sc.AddNavigation(visitor.Navigations);
                        }
                    }

                    // 如果分组后再分页,此时需要在原先的选择字段上再加上 'OrderBy' 子句指定的字段,外层的分页时需要用到这些排序字段
                    if (qQuery.OrderBy.Count > 0 && useOrderBy && groupByPaging)
                    {
                        if (sc.Columns.Count > 0)
                        {
                            jf.Append(",");
                        }
                        for (int i = 0; i < qQuery.OrderBy.Count; i++)
                        {
                            visitor = new ColumnExpressionVisitor(this, aliases, qQuery.OrderBy[i], qQuery.GroupBy, true);
                            visitor.Write(jf);

                            sc.AddNavigation(visitor.Navigations);
                            if (i < qQuery.OrderBy.Count - 1)
                            {
                                jf.AppendNewLine(",");
                            }
                        }
                    }
                }

                #endregion
            }

            // FROM 子句
            jf.AppendNewLine();
            jf.Append("FROM ");
            if (qQuery.Subquery != null)
            {
                // 子查询
                jf.Append("(");
                CommandDefine define = this.ParseSelectCommand <T>(qQuery.Subquery as DbQueryableInfo_Select <T>, indent + 1);
                jf.Append(define.CommandText);
                jf.AppendNewLine();
                jf.Append(")");
            }
            else
            {
                jf.AppendMember(TypeRuntimeInfoCache.GetRuntimeInfo(qQuery.FromType).TableName);
            }
            jf.Append(" t0 ");
            if (!string.IsNullOrEmpty(DbQueryProvider.NOLOCK))
            {
                jf.Append(DbQueryProvider.NOLOCK);
            }

            // LEFT<INNER> JOIN 子句
            visitor = new JoinExpressionVisitor(this, aliases, qQuery.Join);
            visitor.Write(jf);

            wf.Indent = jf.Indent;

            // WHERE 子句
            visitor = new WhereExpressionVisitor(this, aliases, qQuery.Where);
            visitor.Write(wf);
            sc.AddNavigation(visitor.Navigations);

            // GROUP BY 子句
            visitor = new GroupByExpressionVisitor(this, aliases, qQuery.GroupBy);
            visitor.Write(wf);
            sc.AddNavigation(visitor.Navigations);

            // HAVING 子句
            visitor = new HavingExpressionVisitor(this, aliases, qQuery.Having, qQuery.GroupBy);
            visitor.Write(wf);
            sc.AddNavigation(visitor.Navigations);

            // ORDER 子句
            if (qQuery.OrderBy.Count > 0 && useOrderBy && !groupByPaging)
            {
                visitor = new OrderByExpressionVisitor(this, aliases, qQuery.OrderBy, qQuery.GroupBy);
                visitor.Write(wf);
                sc.AddNavigation(visitor.Navigations);
            }

            #region 分页查询

            if (qQuery.Skip > 0 && !groupByPaging)
            {
                if (qQuery.OrderBy.Count == 0)
                {
                    throw new XfwException("The method 'OrderBy' must be called before the method 'Skip'.");
                }
                wf.AppendNewLine();
                wf.Append("OFFSET ");
                wf.Append(qQuery.Skip);
                wf.Append(" ROWS");

                if (qQuery.Take > 0)
                {
                    wf.Append(" FETCH NEXT ");
                    wf.Append(qQuery.Take);
                    wf.Append(" ROWS ONLY ");
                }
            }

            #endregion

            #region 嵌套查询

            if (useStatis && willNest)
            {
                string inner = sc.CommandText;
                indent   -= 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append(" ) t0");
            }

            #endregion

            #region 分组分页

            if (groupByPaging)
            {
                SqlBuilder builder = new SqlBuilder(this.EscCharLeft, this.EscCharRight);

                // SELECT
                int index = -1;
                builder.Append("SELECT ");
                foreach (var kvp in sc.Columns)
                {
                    index += 1;
                    builder.AppendNewLine();
                    builder.AppendMember("t0", kvp.Key);
                    if (index < sc.Columns.Count - 1)
                    {
                        builder.Append(",");
                    }
                }

                builder.AppendNewLine();
                builder.Append("FROM ( ");

                string inner = sc.CommandText;
                //jf.Replace(Environment.NewLine, Environment.NewLine + SqlBuilder.TAB);
                jf.Insert(0, builder);


                indent   -= 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append(" ) t0");

                // 排序
                if (qQuery.OrderBy.Count > 0 && useOrderBy)
                {
                    visitor = new OrderByExpressionVisitor(this, aliases, qQuery.OrderBy, null, "t0");
                    visitor.Write(jf);
                }

                // 分页
                if (qQuery.Skip > 0)
                {
                    jf.AppendNewLine();
                    jf.Append("OFFSET ");
                    jf.Append(qQuery.Skip);
                    jf.Append(" ROWS");

                    if (qQuery.Take > 0)
                    {
                        jf.Append(" FETCH NEXT ");
                        jf.Append(qQuery.Take);
                        jf.Append(" ROWS ONLY ");
                    }
                }
            }

            #endregion

            // 'Any' 子句
            if (qQuery.HaveAny)
            {
                string inner = sc.CommandText;
                indent   -= 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append(") SELECT 1 ELSE SELECT 0");
            }

            // UNION 子句
            if (qQuery.Union != null && qQuery.Union.Count > 0)
            {
                string inner = sc.CommandText;
                for (int index = 0; index < qQuery.Union.Count; index++)
                {
                    jf.AppendNewLine();
                    jf.AppendNewLine("UNION ALL");
                    CommandDefine define = this.ParseSelectCommand <T>(qQuery.Union[index] as DbQueryableInfo_Select <T>);
                    jf.Append(define.CommandText);
                }
            }

            return(sc);
        }
 public static DbExpression VisitFilterPredicate(LambdaExpression lambda, List <IMappingObjectExpression> moeList)
 {
     return(GeneralExpressionVisitor.VisitPredicate(ExpressionVisitorBase.ReBuildFilterPredicate(lambda), moeList));
 }
Esempio n. 30
0
 public static DbExpression ParseFilterPredicate(LambdaExpression lambda, ScopeParameterDictionary scopeParameters, KeyDictionary <string> scopeTables)
 {
     return(GeneralExpressionVisitor.ParseLambda(ExpressionVisitorBase.ReBuildFilterPredicate(lambda), scopeParameters, scopeTables));
 }