示例#1
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));
        }
示例#2
0
        /// <summary>
        /// 创建 UPDATE 命令
        /// </summary>
        /// <param name="dbQuery">查询语义</param>
        /// <param name="token">解析上下文</param>
        /// <returns></returns>
        protected override RawCommand ResolveUpdateCommand <T>(IDbQueryableInfo_Update 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 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.ForeignKey != null)
                    {
                        continue;
                    }
                    if (m.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

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

gotoLabel:

                    if (column == null || !column.IsIdentity)
                    {
                        var value = m.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 m in typeRuntime.KeyMembers)
                {
                    var column = m.Column;
                    var value  = m.Invoke(entity);
                    var seg    = this.DbValue.GetSqlValueWidthDefault(value, token, column);
                    index += 1;

                    seg_Where.AppendMember(m.Member.Name);
                    seg_Where.Append(" = ");
                    seg_Where.Append(seg);
                    if (index < typeRuntime.KeyMembers.Count - 1)
                    {
                        seg_Where.Append(" AND ");
                    }
                }

                builder.Length = length;
                builder.AppendNewLine();
                builder.Append("WHERE ");
                builder.Append(seg_Where);
            }
            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 @init    = body as MemberInitExpression;
                    var bindings = new List <MemberBinding>(@init.Bindings);
                    foreach (var m in typeRuntime.KeyMembers)
                    {
                        var member  = Expression.MakeMemberAccess(lambda.Parameters[0], m.Member);
                        var binding = Expression.Bind(m.Member, member);
                        if (!bindings.Any(x => x.Member == m.Member))
                        {
                            bindings.Add(binding);
                        }
                    }
                    expression = Expression.MemberInit(@init.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 m       = typeRuntime.GetMember(newExpression.Members[i].Name);
                        var binding = Expression.Bind(m.Member, newExpression.Arguments[i].Type != m.DataType
                            ? Expression.Convert(newExpression.Arguments[i], m.DataType)
                            : newExpression.Arguments[i]);
                        bindings.Add(binding);
                    }

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

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

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

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

                    if (typeRuntime.KeyMembers == null || typeRuntime.KeyMembers.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 = (MappingCommand)this.ResolveSelectCommand(dbQuery.Query, 1, false, token);
                    builder.AppendNewLine(cmd.CommandText);
                    builder.Append(") t1 ON (");
                    foreach (var m in typeRuntime.KeyMembers)
                    {
                        builder.AppendMember("t0", m.Name);
                        builder.Append(" = ");
                        builder.AppendMember("t1", m.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 语法
                    TableAlias aliases = this.PrepareTableAlias(dbQuery.Query, token);
                    var        visitor = new UpdateExpressionVisitor(this, aliases, dbQuery.Expression);
                    visitor.Write(builder);

                    var visitor_ = new WhereExpressionVisitor(this, aliases, dbQuery.Query.Where);
                    visitor_.Write(builder);
                }
            }

            builder.Append(';');
            return(new RawCommand(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }