/// <summary>
        /// 构建单表删除的语句,因为不支持多表删除所以单表删除操作由多条语句以主从树形结构来表达需要进行的多批次的删除操作。
        /// </summary>
        /// <param name="context">构建操作需要的数据访问上下文对象。</param>
        /// <returns>返回的单表删除的多条语句的主句。</returns>
        protected virtual IEnumerable <IStatementBase> BuildComplexity(DataDeleteContext context)
        {
            var statement = new DeleteStatement(context.Entity);

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

            if (!context.Schema.IsEmpty)
            {
                this.BuildReturning(statement, context.Schema.Members);
            }

            yield return(statement);
        }
        private void BuildReturning(DeleteStatement statement, IEnumerable <SchemaMember> schemas)
        {
            statement.Returning = new ReturningClause(TableDefinition.Temporary());

            foreach (var key in statement.Entity.Key)
            {
                statement.Returning.Table.Field(key);
                statement.Returning.Append(statement.Table.CreateField(key), ReturningClause.ReturningMode.Deleted);
            }

            var super = statement.Entity.GetBaseEntity();

            while (super != null)
            {
                this.BuildInherit(statement, super);
                super = super.GetBaseEntity();
            }

            foreach (var schema in schemas)
            {
                if (schema.Token.Property.IsSimplex)
                {
                    continue;
                }

                var     complex = (IDataEntityComplexProperty)schema.Token.Property;
                ISource src     = null;

                if (complex.Entity == statement.Entity)
                {
                    src = statement.Table;
                }
                else
                {
                    src = statement.Join(statement.Table, complex.Entity);
                }

                foreach (var link in complex.Links)
                {
                    //某些导航属性可能与主键相同,表定义的字段定义方法(TableDefinition.Field(...))可避免同名字段的重复定义
                    if (statement.Returning.Table.Field(link.Principal) != null)
                    {
                        statement.Returning.Append(src.CreateField(link.Name), ReturningClause.ReturningMode.Deleted);
                    }
                }

                this.BuildSlave(statement, schema);
            }
        }
示例#3
0
        private DeleteStatement BuildSlave(TableDefinition master, SchemaMember schema)
        {
            var complex   = (IEntityComplexPropertyMetadata)schema.Token.Property;
            var statement = new DeleteStatement(complex.Foreign);
            var reference = TableIdentifier.Temporary(master.Name, TEMPORARY_ALIAS);

            if (complex.Links.Length == 1)
            {
                var select = new SelectStatement(reference);
                select.Select.Members.Add(reference.CreateField(complex.Links[0].Name));
                statement.Where = Expression.In(statement.Table.CreateField(complex.Links[0].Role), select);
            }
            else
            {
                var join = new JoinClause(TEMPORARY_ALIAS, reference, JoinType.Inner);

                foreach (var link in complex.Links)
                {
                    join.Condition.Add(
                        Expression.Equal(
                            statement.Table.CreateField(link.Role),
                            reference.CreateField(link.Name)));
                }

                statement.From.Add(join);
            }

            var super = statement.Entity.GetBaseEntity();

            if (super != null || schema.HasChildren)
            {
                var temporary = this.BuildMaster(statement, schema.Children);
                master.Slaves.Add(temporary);

                //if(schema.HasChildren)
                //{
                //	foreach(var child in schema.Children)
                //	{
                //		this.BuildSlave(temporary, child);
                //	}
                //}
            }
            else
            {
                master.Slaves.Add(statement);
            }

            return(statement);
        }
        private DeleteStatement BuildSlave(Aliaser aliaser, DeleteStatement master, SchemaMember schema)
        {
            var complex   = (IDataEntityComplexProperty)schema.Token.Property;
            var statement = new DeleteStatement(complex.Foreign);
            var reference = master.Returning.Table.Identifier();

            if (complex.Links.Length == 1)
            {
                var select = new SelectStatement(reference);
                select.Select.Members.Add(reference.CreateField(complex.Links[0].GetAnchors().Last()));
                statement.Where = Expression.In(statement.Table.CreateField(complex.Links[0].Foreign), select);
            }
            else
            {
                var join = new JoinClause(TEMPORARY_ALIAS, reference, JoinType.Inner);

                foreach (var link in complex.Links)
                {
                    var anchor = link.GetAnchors().Last();

                    join.Conditions.Add(
                        Expression.Equal(
                            statement.Table.CreateField(link.Foreign),
                            reference.CreateField(anchor.Name)));
                }

                statement.From.Add(join);
            }

            var super = statement.Entity.GetBaseEntity();

            if (super != null || schema.HasChildren)
            {
                this.BuildReturning(aliaser, statement, schema.Children);
            }
            else
            {
                master.Slaves.Add(statement);
            }

            return(statement);
        }
        /// <summary>
        /// 构建支持多表删除的语句。
        /// </summary>
        /// <param name="context">构建操作需要的数据访问上下文对象。</param>
        /// <returns>返回多表删除的语句。</returns>
        protected virtual IEnumerable <IStatementBase> BuildSimplicity(DataDeleteContext context)
        {
            var statement = new DeleteStatement(context.Entity);

            //构建当前实体的继承链的关联集
            this.Join(statement, statement.Table).ToArray();

            //获取要删除的数据模式(模式不为空)
            if (!context.Schema.IsEmpty)
            {
                //依次生成各个数据成员的关联(包括它的继承链、子元素集)
                foreach (var schema in context.Schema.Members)
                {
                    this.Join(statement, statement.Table, schema);
                }
            }

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

            yield return(statement);
        }
        private void Join(DeleteStatement statement, TableIdentifier table, SchemaMember schema)
        {
            if (table == null || schema == null || schema.Token.Property.IsSimplex)
            {
                return;
            }

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

            var join   = statement.Join(table, schema);
            var target = (TableIdentifier)join.Target;

            statement.Tables.Add(target);

            //生成当前导航属性表的继承链关联集
            var joins = this.Join(statement, target, schema.FullPath);

            if (schema.HasChildren)
            {
                foreach (var child in schema.Children)
                {
                    if (joins != null)
                    {
                        join = joins.FirstOrDefault(j => ((TableIdentifier)j.Target).Entity == child.Token.Property.Entity);

                        if (join != null)
                        {
                            target = (TableIdentifier)join.Target;
                        }
                    }

                    this.Join(statement, target, child);
                }
            }
        }
        private void BuildReturning(Aliaser aliaser, DeleteStatement statement, IEnumerable <SchemaMember> schemas)
        {
            statement.Returning = new ReturningClause(TableDefinition.Temporary());

            foreach (var key in statement.Entity.Key)
            {
                statement.Returning.Table.Field(key);
                statement.Returning.Append(statement.Table.CreateField(key), ReturningClause.ReturningMode.Deleted);
            }

            var super = statement.Entity.GetBaseEntity();

            while (super != null)
            {
                this.BuildInherit(aliaser, statement, super);
                super = super.GetBaseEntity();
            }

            foreach (var schema in schemas)
            {
                if (schema.Token.Property.IsSimplex)
                {
                    continue;
                }

                var     complex = (IDataEntityComplexProperty)schema.Token.Property;
                ISource src     = complex.Entity == statement.Entity ?
                                  statement.Table :
                                  statement.Join(aliaser, statement.Table, complex.Entity);

                foreach (var link in complex.Links)
                {
                    var anchors = link.GetAnchors();

                    if (anchors.Length > 1)
                    {
                        continue;
                    }

                    ISource source = statement.Table;

                    foreach (var anchor in link.GetAnchors())
                    {
                        if (anchor.IsComplex)
                        {
                            source = statement.Join(aliaser, source, (IDataEntityComplexProperty)anchor);
                        }
                        else
                        {
                            //某些导航属性可能与主键相同,表定义的字段定义方法(TableDefinition.Field(...))可避免同名字段的重复定义
                            if (statement.Returning.Table.Field((IDataEntitySimplexProperty)anchor) != null)
                            {
                                statement.Returning.Append(src.CreateField(anchor.Name), ReturningClause.ReturningMode.Deleted);
                            }
                        }
                    }
                }

                this.BuildSlave(aliaser, statement, schema);
            }
        }