Esempio n. 1
0
 protected override Expression Accept(DbExpressionVisitor visitor)
 {
     return(visitor.VisitLike(this));
 }
Esempio n. 2
0
 public override T Accept <T>(DbExpressionVisitor <T> visitor)
 {
     return(visitor.Visit(this));
 }
Esempio n. 3
0
 protected override Expression Accept(DbExpressionVisitor visitor)
 {
     return(visitor.VisitSqlFunction(this));
 }
Esempio n. 4
0
 protected override Expression Accept(DbExpressionVisitor visitor)
 {
     return(visitor.VisitSqlConstant(this));
 }
Esempio n. 5
0
 protected override Expression Accept(DbExpressionVisitor visitor)
 {
     return(visitor.VisitCommandAggregate(this));
 }
Esempio n. 6
0
 protected override Expression Accept(DbExpressionVisitor visitor)
 {
     return(visitor.VisitSelectRowCount(this));
 }
Esempio n. 7
0
 protected override Expression Accept(DbExpressionVisitor visitor)
 {
     return(visitor.VisitRowNumber(this));
 }
Esempio n. 8
0
 protected override Expression Accept(DbExpressionVisitor visitor)
 {
     return(visitor.VisitChildProjection(this));
 }
Esempio n. 9
0
 protected override Expression Accept(DbExpressionVisitor visitor)
 {
     return(visitor.VisitAggregateRequest(this));
 }
Esempio n. 10
0
 protected override Expression Accept(DbExpressionVisitor visitor)
 {
     return(visitor.VisitIsNotNull(this));
 }
 /// <summary>
 /// 创建方法表达式访问器
 /// </summary>
 /// <param name="visitor">表达式访问器</param>
 /// <returns></returns>
 protected internal override MethodCallExpressionVisitor CreateMethodCallVisitor(DbExpressionVisitor visitor) => new SQLiteMethodCallExressionVisitor(visitor);
        /// <summary>
        /// 创建 UPDATE 命令
        /// </summary>
        /// <param name="tree">查询语义</param>
        /// <param name="context">解析SQL命令上下文</param>
        /// <returns></returns>
        protected override DbRawCommand TranslateUpdateCommand <T>(DbQueryUpdateTree tree, ITranslateContext context)
        {
            ISqlBuilder builder     = this.CreateSqlBuilder(context);
            var         typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            builder.Append("UPDATE ");
            builder.AppendTable(typeRuntime.TableSchema, typeRuntime.TableName, typeRuntime.IsTemporary);
            builder.Append(" SET");
            builder.AppendNewLine();

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

                foreach (var item in typeRuntime.Members)
                {
                    var m = item as FieldAccessorBase;
                    if (m == null || !m.IsDbField)
                    {
                        continue;
                    }

                    if (m.Column != null && m.Column.IsIdentity)
                    {
                        goto LABEL;                                          // Fix issue# 自增列同时又是主键
                    }
                    if (m.Column != null && m.Column.DbType is SqlDbType && (SqlDbType)m.Column.DbType == SqlDbType.Timestamp)
                    {
                        continue;                                                                                                        // 行版本号
                    }
                    builder.AppendMember(null, m.Member, typeRuntime.Type);
                    builder.Append(" = ");

LABEL:
                    var value = m.Invoke(entity);
                    var sqlExpression = this.Constor.GetSqlValueWidthDefault(value, context, m.Column);

                    if (m.Column == null || !m.Column.IsIdentity)
                    {
                        builder.Append(sqlExpression);
                        length = builder.Length;
                        builder.Append(',');
                        builder.AppendNewLine();
                    }

                    if (m.Column != null && m.Column.IsKey)
                    {
                        useKey = true;
                        whereBuilder.AppendMember(null, m.Member, typeRuntime.Type);
                        whereBuilder.Append(" = ");
                        whereBuilder.Append(sqlExpression);
                        whereBuilder.Append(" AND ");
                    }
                }

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

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

                builder.AppendNewLine();
                builder.Append("WHERE ");
                builder.Append(whereBuilder);
            }
            else if (tree.Expression != null)
            {
                // SELECT 表达式
                LambdaExpression lambda = tree.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 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(memberInit.NewExpression, bindings);
                }
                else if (body.NodeType == ExpressionType.New)
                {
                    var newExpression = body as NewExpression;
                    var bindings      = new List <MemberBinding>();
                    for (int index = 0; index < newExpression.Members.Count; index++)
                    {
                        var m = (FieldAccessorBase)typeRuntime.Members.FirstOrDefault(a => a is FieldAccessorBase && (
                                                                                          a.Name == newExpression.Members[index].Name ||
                                                                                          ((FieldAccessorBase)a).Column != null && ((FieldAccessorBase)a).Column.Name == newExpression.Members[index].Name));
                        if (m == null)
                        {
                            throw new XFrameworkException("Member {0}.{1} not found.", typeRuntime.Type.Name, newExpression.Members[index].Name);
                        }
                        var binding = Expression.Bind(m.Member, newExpression.Arguments[index].Type != m.CLRType
                            ? Expression.Convert(newExpression.Arguments[index], m.CLRType)
                            : newExpression.Arguments[index]);
                        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.Member);
                    expression = Expression.MemberInit(newExpression2, bindings);
                }

                // 解析查询以确定是否需要嵌套
                tree.Select.Select = new DbExpression(DbExpressionType.Select, expression);
                var cmd = (DbSelectCommand)this.TranslateSelectCommand(tree.Select, 0, false, this.CreateTranslateContext(context.DbContext));

                if ((cmd.NavMembers != null && cmd.NavMembers.Count > 0) || (tree.Select.Joins != null && tree.Select.Joins.Count > 0))
                {
                    if (typeRuntime.KeyMembers == null || typeRuntime.KeyMembers.Count == 0)
                    {
                        throw new XFrameworkException("Update<T>(Expression<Func<T, object>> updateExpression) require entity must have key column.");
                    }

                    // SET 字段
                    var visitor = new SQLiteUpdateExpressionVisitor(null, builder, tree, null);
                    visitor.Translator = this.TranslateSelectCommand;
                    visitor.Visit(tree.Expression);

                    // WHERE部分
                    builder.AppendNewLine();
                    builder.Append("WHERE EXISTS");
                    visitor.VisitArgument(tree.Select.Select.Expressions[0], true);
                }
                else
                {
                    // 直接 SQL 的 UPDATE 语法
                    DbExpressionVisitor visitor = null;
                    AliasGenerator      ag      = this.PrepareTableAlias(tree.Select, context.AliasPrefix);
                    visitor = new SQLiteUpdateExpressionVisitor(ag, builder, tree, null);
                    ((SQLiteUpdateExpressionVisitor)visitor).Translator = this.TranslateSelectCommand;
                    visitor.Visit(tree.Expression);

                    if (tree.Select.Wheres != null)
                    {
                        visitor = new WhereExpressionVisitor(null, builder);
                        visitor.Visit(tree.Select.Wheres);
                    }
                }
            }

            builder.Append(';');
            return(new DbRawCommand(builder.ToString(), builder.TranslateContext != null ? builder.TranslateContext.Parameters : null, System.Data.CommandType.Text));
        }
        /// <summary>
        /// 创建 UPDATE 命令
        /// </summary>
        /// <param name="tree">查询语义</param>
        /// <param name="context">解析SQL命令上下文</param>
        /// <returns></returns>
        protected override DbRawCommand TranslateUpdateCommand <T>(DbQueryUpdateTree tree, ITranslateContext context)
        {
            // 增删改不用 NOLOCK
            bool noLock = ((SqlServerDbContext)context.DbContext).NoLock;

            ((SqlServerDbContext)context.DbContext).NoLock = false;

            ISqlBuilder builder     = this.CreateSqlBuilder(context);
            var         typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

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

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

                foreach (var item in typeRuntime.Members)
                {
                    var m = item as FieldAccessorBase;
                    if (m == null || !m.IsDbField)
                    {
                        continue;
                    }

                    // Fix issue# 自增列同时又是主键
                    if (m.Column != null && m.Column.IsIdentity)
                    {
                        goto LABEL;
                    }
                    // 忽略行版本号列
                    if (m.Column != null && m.Column.DbType is SqlDbType && (SqlDbType)m.Column.DbType == SqlDbType.Timestamp)
                    {
                        continue;
                    }

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

LABEL:
                    var value = m.Invoke(entity);
                    var sqlExpression = this.Constor.GetSqlValueWidthDefault(value, context, m.Column);

                    if (m.Column == null || !m.Column.IsIdentity)
                    {
                        builder.Append(sqlExpression);
                        length = builder.Length;
                        builder.Append(',');
                        builder.AppendNewLine();
                    }

                    if (m.Column != null && m.Column.IsKey)
                    {
                        useKey = true;
                        whereBuilder.AppendMember("t0", m.Member, typeRuntime.Type);
                        whereBuilder.Append(" = ");
                        whereBuilder.Append(sqlExpression);
                        whereBuilder.Append(" AND ");
                    }
                }

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

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

                builder.AppendNewLine();
                builder.Append("FROM ");
                builder.AppendTable(typeRuntime.TableSchema, typeRuntime.TableName, typeRuntime.IsTemporary);
                builder.Append(" t0");

                builder.AppendNewLine();
                builder.Append("WHERE ");
                builder.Append(whereBuilder);
            }
            else if (tree.Expression != null)
            {
                AliasGenerator      ag      = this.PrepareTableAlias(tree.Select, context.AliasPrefix);
                DbExpressionVisitor visitor = null;
                visitor = new UpdateExpressionVisitor(ag, builder);
                visitor.Visit(tree.Expression);

                builder.AppendNewLine();
                builder.Append("FROM ");
                builder.AppendTable(typeRuntime.TableSchema, typeRuntime.TableName, typeRuntime.IsTemporary);
                builder.AppendAs("t0");

                var cmd = new SqlServerDbSelectCommand(context, ag, tree.Select.SelectHasMany);
                if (tree.Select.Joins != null)
                {
                    visitor = new SqlServerJoinExpressionVisitor(ag, cmd.JoinFragment);
                    visitor.Visit(tree.Select.Joins);
                }

                if (tree.Select.Wheres != null)
                {
                    visitor = new WhereExpressionVisitor(ag, cmd.WhereFragment);
                    visitor.Visit(tree.Select.Wheres);
                    cmd.AddNavMembers(visitor.NavMembers);
                }

                builder.Append(cmd.CommandText);
            }

            ((SqlServerDbContext)context.DbContext).NoLock = noLock;

            return(new DbRawCommand(builder.ToString(), builder.TranslateContext != null ? builder.TranslateContext.Parameters : null, System.Data.CommandType.Text));
        }