Exemple #1
0
        private IExpression Where(DataUpdateContext context, UpdateStatement statement)
        {
            if (context.IsMultiple || context.Criteria == null)
            {
                var criteria = new ConditionExpression(ConditionCombination.And);

                foreach (var key in statement.Entity.Key)
                {
                    if (!statement.Entity.GetTokens(context.ModelType).TryGet(key.Name, out var token))
                    {
                        throw new DataException($"No required primary key field values were specified for the updation '{statement.Entity.Name}' entity data.");
                    }

                    var field     = statement.Table.CreateField(key);
                    var parameter = Expression.Parameter(field, new SchemaMember(token));

                    criteria.Add(Expression.Equal(field, parameter));
                    statement.Parameters.Add(parameter);
                }

                criteria.Add(statement.Where(context.Validate(), context.Aliaser));

                return(criteria.Count > 0 ? criteria : null);
            }

            return(statement.Where(context.Validate(), context.Aliaser));
        }
Exemple #2
0
        private TableIdentifier Join(Aliaser aliaser, UpdateStatement statement, SchemaMember schema)
        {
            if (schema == null || schema.Token.Property.IsSimplex)
            {
                return(null);
            }

            //获取关联的源
            ISource source = schema.Parent == null ?
                             statement.Table :
                             statement.From.Get(schema.Path);

            //第一步:处理模式成员所在的继承实体的关联
            if (schema.Ancestors != null)
            {
                foreach (var ancestor in schema.Ancestors)
                {
                    source = statement.Join(aliaser, source, ancestor, schema.FullPath);
                }
            }

            //第二步:处理模式成员(导航属性)的关联
            var join   = statement.Join(aliaser, source, schema);
            var target = (TableIdentifier)join.Target;

            statement.Tables.Add(target);

            //返回关联的目标表
            return(target);
        }
Exemple #3
0
        private void BuildComplexStandalone(DataUpdateContext context, UpdateStatement statement, object data, SchemaMember member)
        {
            if (!member.HasChildren)
            {
                return;
            }

            var complex = (IDataEntityComplexProperty)member.Token.Property;

            statement.Returning = new ReturningClause(TableDefinition.Temporary());

            var slave = new UpdateStatement(complex.Foreign, member);

            statement.Slaves.Add(slave);

            //创建从属更新语句的条件子查询语句
            var selection = new SelectStatement(statement.Returning.Table.Identifier());

            foreach (var link in complex.Links)
            {
                ISource source = statement.Table;

                foreach (var anchor in link.GetAnchors())
                {
                    if (anchor.IsComplex)
                    {
                        source = statement.Join(context.Aliaser, source, (IDataEntityComplexProperty)anchor);
                    }
                    else
                    {
                        if (statement.Returning.Table.Field((IDataEntitySimplexProperty)anchor) != null)
                        {
                            statement.Returning.Append(source.CreateField(anchor.Name), ReturningClause.ReturningMode.Deleted);
                        }

                        var field = selection.Table.CreateField(anchor);
                        selection.Select.Members.Add(field);

                        if (selection.Where == null)
                        {
                            selection.Where = Expression.Equal(field, slave.Table.CreateField(link.ForeignKey));
                        }
                        else
                        {
                            selection.Where = Expression.AndAlso(slave.Where,
                                                                 Expression.Equal(field, slave.Table.CreateField(link.ForeignKey)));
                        }
                    }
                }
            }

            slave.Where = Expression.Exists(selection);

            foreach (var child in member.Children)
            {
                this.BuildSchema(context, slave, slave.Table, member.Token.GetValue(data), child);
            }
        }
Exemple #4
0
        /// <summary>
        /// 构建单表更新的语句,因为不支持多表更新所以单表更新操作由多条语句以主从树形结构来表达需要进行的多批次的更新操作。
        /// </summary>
        /// <param name="context">构建操作需要的数据访问上下文对象。</param>
        /// <returns>返回的单表更新的多条语句的主句。</returns>
        protected virtual IEnumerable <IStatementBase> BuildComplexity(DataUpdateContext context)
        {
            var statement = new UpdateStatement(context.Entity);

            //生成条件子句
            statement.Where = this.Where(context, statement);

            return(null);
        }
Exemple #5
0
        private void BuildComplex(DataUpdateContext context, UpdateStatement statement, object data, SchemaMember member)
        {
            if (!member.HasChildren)
            {
                return;
            }

            var table = this.Join(context.Aliaser, statement, member);

            foreach (var child in member.Children)
            {
                BuildSchema(context, statement, table, member.Token.GetValue(data), child);
            }
        }
Exemple #6
0
        public IEnumerable <IStatementBase> Build(DataIncrementContext context)
        {
            var statement = new UpdateStatement(context.Entity);

            var source = statement.From(context.Member, context.Aliaser, null, out var property);
            var field  = source.CreateField(property);
            var value  = context.Interval > 0 ?
                         Expression.Add(field, Expression.Constant(context.Interval)) :
                         Expression.Subtract(field, Expression.Constant(-context.Interval));

            //添加修改字段
            statement.Fields.Add(new FieldValue(field, value));

            //构建WHERE子句
            statement.Where = statement.Where(context.Validate(), context.Aliaser);

            if (context.Source.Features.Support(Feature.Updation.Outputting))
            {
                statement.Returning = new ReturningClause();
                statement.Returning.Append(field, ReturningClause.ReturningMode.Inserted);
            }
            else
            {
                var slave = new SelectStatement();

                foreach (var from in statement.From)
                {
                    slave.From.Add(from);
                }

                slave.Where = statement.Where;
                slave.Select.Members.Add(field);

                //注:由于从属语句的WHERE子句只是简单的指向父语句的WHERE子句,
                //因此必须手动将父语句的参数依次添加到从属语句中。
                foreach (var parameter in statement.Parameters)
                {
                    slave.Parameters.Add(parameter);
                }

                statement.Slaves.Add(slave);
            }

            yield return(statement);
        }
Exemple #7
0
        private void BuildSchema(DataUpdateContext context, UpdateStatement statement, TableIdentifier table, object data, SchemaMember member)
        {
            //忽略主键修改,即不能修改主键
            if (member.Token.Property.IsPrimaryKey)
            {
                return;
            }

            //如果不是批量更新,并且当前成员没有改动则返回
            if (!context.IsMultiple && !this.HasChanges(data, member.Name))
            {
                return;
            }

            if (member.Token.Property.IsSimplex)
            {
                var field     = table.CreateField(member.Token);
                var parameter = Expression.Parameter(ParameterExpression.Anonymous, member, field);

                statement.Fields.Add(new FieldValue(field, parameter));
                statement.Parameters.Add(parameter);
            }
            else
            {
                var complex = (IEntityComplexPropertyMetadata)member.Token.Property;

                if (complex.Multiplicity == AssociationMultiplicity.Many)
                {
                    this.BuildUpsertion(statement, member);
                }
                else
                {
                    table = this.Join(statement, member);

                    if (member.HasChildren)
                    {
                        foreach (var child in member.Children)
                        {
                            BuildSchema(context, statement, table, member.Token.GetValue(data), child);
                        }
                    }
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// 构建支持多表更新的语句。
        /// </summary>
        /// <param name="context">构建操作需要的数据访问上下文对象。</param>
        /// <returns>返回多表更新的语句。</returns>
        protected virtual IEnumerable <IStatementBase> BuildSimplicity(DataUpdateContext context)
        {
            var statement = new UpdateStatement(context.Entity);

            //获取要更新的数据模式(模式不为空)
            if (!context.Schema.IsEmpty)
            {
                //依次生成各个数据成员的关联(包括它的子元素集)
                foreach (var member in context.Schema.Members)
                {
                    this.BuildSchema(context, statement, statement.Table, context.Data, member);
                }
            }

            //生成条件子句
            statement.Where = this.Where(context, statement);

            yield return(statement);
        }
Exemple #9
0
        public IEnumerable <IStatementBase> Build(DataUpdateContext context)
        {
            var statement = new UpdateStatement(context.Entity);

            //获取要更新的数据模式(模式不为空)
            if (!context.Schema.IsEmpty)
            {
                //依次生成各个数据成员的关联(包括它的子元素集)
                foreach (var member in context.Schema.Members)
                {
                    this.BuildSchema(context, statement, statement.Table, context.Data, member);
                }
            }

            //生成条件子句
            statement.Where = this.Where(context, statement);

            if (statement.Fields.Count == 0)
            {
                throw new DataException($"The update statement is missing a required set clause.");
            }

            yield return(statement);
        }
Exemple #10
0
        private void BuildSchema(DataUpdateContext context, UpdateStatement statement, TableIdentifier table, object data, SchemaMember member)
        {
            //如果不允许更新主键,则忽略对主键修改的构建
            if (member.Token.Property.IsPrimaryKey && !context.Options.HasBehaviors(UpdateBehaviors.PrimaryKey))
            {
                return;
            }

            //确认指定成员是否有必须的写入值
            var provided = context.Validate(member.Token.Property, out var value);

            //如果不是批量更新,并且指定成员不是必须要生成的且也没有必须写入的值,则返回
            if (!context.IsMultiple && !Utility.IsGenerateRequired(ref data, member.Name) && !provided)
            {
                return;
            }

            if (member.Token.Property.IsSimplex)
            {
                //忽略不可变属性
                if (member.Token.Property.Immutable && !provided)
                {
                    return;
                }

                //创建当前单值属性的对应的字段标识
                var field = table.CreateField(member.Token);

                if (typeof(Operand).IsAssignableFrom(member.Token.MemberType))
                {
                    var operand    = (Operand)member.Token.GetValue(data);
                    var expression = this.OperandConverter.Convert(context, statement, operand);
                    statement.Fields.Add(new FieldValue(field, expression));
                }
                else
                {
                    var parameter = provided ?
                                    Expression.Parameter(field, member, value) :
                                    Expression.Parameter(field, member);

                    statement.Parameters.Add(parameter);

                    //如果当前的数据成员类型为递增步长类型则生成递增表达式
                    if (member.Token.MemberType == typeof(Interval))
                    {
                        /*
                         * 注:默认参数类型为对应字段的类型,而该字段类型可能为无符号数,
                         * 因此当参数类型为无符号数并且步长为负数(递减),则可能导致参数类型转换溢出,
                         * 所以必须将该参数类型重置为有符号整数。
                         */
                        parameter.DbType = System.Data.DbType.Int32;

                        //字段设置项的值为「字段+参数」的加法表达式
                        statement.Fields.Add(new FieldValue(field, field.Add(parameter)));
                    }
                    else
                    {
                        //字段设置项的值即为参数
                        statement.Fields.Add(new FieldValue(field, parameter));
                    }
                }
            }
            else
            {
                //不可变复合属性不支持任何写操作,即在修改操作中不能包含不可变复合属性
                if (member.Token.Property.Immutable)
                {
                    throw new DataException($"The '{member.FullPath}' is an immutable complex(navigation) property and does not support the update operation.");
                }

                var complex = (IDataEntityComplexProperty)member.Token.Property;

                if (complex.Multiplicity == DataAssociationMultiplicity.Many)
                {
                    //注:在构建一对多的导航属性的UPSERT语句时不能指定容器数据(即data参数值为空),因为批量操作语句不支持在构建阶段绑定到具体数据
                    var upserts = UpsertStatementBuilder.BuildUpserts(context, complex.Foreign, null, member, member.Children);

                    //将新建的语句加入到主语句的从属集中
                    foreach (var upsert in upserts)
                    {
                        statement.Slaves.Add(upsert);
                    }
                }
                else
                {
                    if (context.Source.Features.Support(Feature.Updation.Multitable))
                    {
                        this.BuildComplex(context, statement, data, member);
                    }
                    else
                    {
                        this.BuildComplexStandalone(context, statement, data, member);
                    }
                }
            }
        }
Exemple #11
0
        private void BuildSchema(DataUpdateContext context, UpdateStatement statement, TableIdentifier table, object data, SchemaMember member)
        {
            //忽略主键修改,即不能修改主键
            if (member.Token.Property.IsPrimaryKey)
            {
                return;
            }

            //确认指定成员是否有必须的写入值
            var provided = context.Validate(member.Token.Property, out var value);

            //如果不是批量更新,并且指定成员不是必须要生成的且也没有必须写入的值,则返回
            if (!context.IsMultiple && !Utility.IsGenerateRequired(ref data, member.Name) && !provided)
            {
                return;
            }

            if (member.Token.Property.IsSimplex)
            {
                //忽略不可变属性
                if (member.Token.Property.Immutable && !provided)
                {
                    return;
                }

                var field     = table.CreateField(member.Token);
                var parameter = provided ?
                                Expression.Parameter(field, member, value) :
                                Expression.Parameter(field, member);

                //如果当前的数据成员类型为递增步长类型则生成递增表达式
                if (member.Token.MemberType == typeof(Interval))
                {
                    /*
                     * 注:默认参数类型为对应字段的类型,而该字段类型可能为无符号数,
                     * 因此当参数类型为无符号数并且步长为负数(递减),则可能导致参数类型转换溢出,
                     * 所以必须将该参数类型重置为有符号整数。
                     */
                    parameter.DbType = System.Data.DbType.Int32;

                    //字段设置项的值为字段加参数的加法表达式
                    statement.Fields.Add(new FieldValue(field, field.Add(parameter)));
                }
                else
                {
                    statement.Fields.Add(new FieldValue(field, parameter));
                }

                statement.Parameters.Add(parameter);
            }
            else
            {
                //不可变复合属性不支持任何写操作,即在修改操作中不能包含不可变复合属性
                if (member.Token.Property.Immutable)
                {
                    throw new DataException($"The '{member.FullPath}' is an immutable complex(navigation) property and does not support the update operation.");
                }

                var complex = (IDataEntityComplexProperty)member.Token.Property;

                if (complex.Multiplicity == DataAssociationMultiplicity.Many)
                {
                    var upserts = UpsertStatementBuilder.BuildUpserts(context, complex.Foreign, data, member, member.Children);

                    //将新建的语句加入到主语句的从属集中
                    foreach (var upsert in upserts)
                    {
                        statement.Slaves.Add(upsert);
                    }
                }
                else
                {
                    if (context.Source.Features.Support(Feature.Updation.Multitable))
                    {
                        this.BuildComplex(context, statement, data, member);
                    }
                    else
                    {
                        this.BuildComplexStandalone(context, statement, data, member);
                    }
                }
            }
        }