Ejemplo n.º 1
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);
            }
        }
Ejemplo n.º 2
0
        private TableDefinition BuildMaster(DeleteStatement statement, IEnumerable <SchemaMember> schemas)
        {
            var master = TableDefinition.Temporary();

            master.Slaves.Add(statement);

            statement.Returning = new ReturningClause(TableIdentifier.Temporary(master.Name));

            foreach (var key in statement.Entity.Key)
            {
                master.Field(key);
                statement.Returning.Fields.Add(statement.Table.CreateField(key));
            }

            var super = statement.Entity.GetBaseEntity();

            while (super != null)
            {
                this.BuildSlave(master, super);
                super = super.GetBaseEntity();
            }

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

                    var     complex = (IEntityComplexPropertyMetadata)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 (master.Field(link.Principal) != null)
                        {
                            statement.Returning.Fields.Add(src.CreateField(link.Name));
                        }
                    }

                    this.BuildSlave(master, schema);
                }
            }

            return(master);
        }
        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);
            }
        }
Ejemplo n.º 4
0
        private void GenerateSchema(SelectStatement statement, ISource origin, SchemaMember member)
        {
            if (member.Ancestors != null)
            {
                foreach (var ancestor in member.Ancestors)
                {
                    origin = statement.Join(origin, ancestor, member.Path);
                }
            }

            if (member.Token.Property.IsComplex)
            {
                var complex = (IDataEntityComplexProperty)member.Token.Property;

                //一对多的导航属性对应一个新语句(新语句别名即为该导航属性的全称)
                if (complex.Multiplicity == DataAssociationMultiplicity.Many)
                {
                    var slave = new SelectStatement(complex.Foreign, member.FullPath)
                    {
                        Paging = member.Paging
                    };
                    var table = slave.Table;

                    if (complex.ForeignProperty != null)
                    {
                        if (complex.ForeignProperty.IsSimplex)
                        {
                            slave.Select.Members.Add(slave.Table.CreateField(complex.ForeignProperty));
                        }
                        else
                        {
                            table = (TableIdentifier)slave.Join(slave.Table, (IDataEntityComplexProperty)complex.ForeignProperty).Target;
                        }
                    }

                    statement.Slaves.Add(slave);

                    //为一对多的导航属性增加必须的链接字段及对应的条件参数
                    foreach (var link in complex.Links)
                    {
                        var principalField = origin.CreateField(link.Principal);
                        principalField.Alias = "$" + member.FullPath + ":" + link.Name;
                        statement.Select.Members.Add(principalField);

                        var foreignField = slave.Table.CreateField(link.Foreign);
                        foreignField.Alias = null;
                        if (slave.Where == null)
                        {
                            slave.Where = Expression.Equal(foreignField, slave.Parameters.Add(link.Name, link.Foreign.Type));
                        }
                        else
                        {
                            slave.Where = Expression.AndAlso(slave.Where,
                                                             Expression.Equal(foreignField, slave.Parameters.Add(link.Name, link.Foreign.Type)));
                        }
                    }

                    //为导航属性增加约束过滤条件
                    if (complex.HasConstraints())
                    {
                        foreach (var constraint in complex.Constraints)
                        {
                            slave.Where = Expression.AndAlso(slave.Where,
                                                             Expression.Equal(
                                                                 table.CreateField(constraint.Name),
                                                                 complex.GetConstraintValue(constraint)));
                        }
                    }

                    if (member.Sortings != null)
                    {
                        this.GenerateSortings(slave, table, member.Sortings);
                    }

                    if (member.HasChildren)
                    {
                        foreach (var child in member.Children)
                        {
                            this.GenerateSchema(slave, table, child);
                        }
                    }

                    return;
                }

                //对于一对一的导航属性,创建其关联子句即可
                origin = statement.Join(origin, complex, member.FullPath);

                //确保导航属性的外链表的主键都在
                if (member.HasChildren)
                {
                    foreach (var key in complex.Foreign.Key)
                    {
                        if (!member.Children.Contains(key.Name))
                        {
                            member.Append(new SchemaMember(key));
                        }
                    }
                }
            }
            else
            {
                var field = origin.CreateField(member.Token.Property);

                //只有数据模式元素是导航子元素以及与当前语句的别名不同(相同则表示为同级),才需要指定字段引用的别名
                if (member.Parent != null && !string.Equals(member.Path, statement.Alias, StringComparison.OrdinalIgnoreCase))
                {
                    if (string.IsNullOrEmpty(statement.Alias))
                    {
                        field.Alias = member.FullPath;
                    }
                    else
                    {
                        field.Alias = Zongsoft.Common.StringExtension.TrimStart(member.FullPath, statement.Alias + ".", StringComparison.OrdinalIgnoreCase);
                    }
                }

                statement.Select.Members.Add(field);
            }

            if (member.HasChildren)
            {
                foreach (var child in member.Children)
                {
                    this.GenerateSchema(statement, origin, child);
                }
            }
        }
Ejemplo n.º 5
0
        private IExpression GenerateAggregate(TContext context, IStatementBase statement, Operand.AggregateOperand aggregate)
        {
            var                 entity = this.GetEntity(context);
            SelectStatement     selection;
            IDataEntityProperty property;
            FieldIdentifier     field;
            var                 parts = aggregate.Member.Split('.', StringSplitOptions.RemoveEmptyEntries);

            switch (parts.Length)
            {
            case 1:
                if (!entity.Properties.TryGet(parts[0], out property))
                {
                    throw new DataException($"The specified '{parts[0]}' field does not exist in the '{entity.Name}' entity.");
                }

                selection = new SelectStatement(entity);
                field     = selection.Table.CreateField(property);
                selection.Select.Members.Add(new AggregateExpression(aggregate.Function, aggregate.Distinct, field));

                break;

            case 2:
                if (!entity.Properties.TryGet(parts[0], out property))
                {
                    throw new DataException($"The specified '{parts[0]}' field does not exist in the '{entity.Name}' entity.");
                }

                if (property.IsSimplex)
                {
                    throw new DataException($"The specified '{parts[0]}' is a simple property and cannot be navigated.");
                }

                var complex = (IDataEntityComplexProperty)property;

                selection = new SelectStatement(complex.Foreign);
                field     = selection.Table.CreateField(complex.Foreign.Properties.Get(parts[1]));
                selection.Select.Members.Add(new AggregateExpression(aggregate.Function, aggregate.Distinct, field));

                var conditions = ConditionExpression.And();

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

                    foreach (var anchor in link.GetAnchors())
                    {
                        if (anchor.IsComplex)
                        {
                            src = selection.Join(context.Aliaser, selection, (IDataEntityComplexProperty)anchor);
                        }
                        else
                        {
                            conditions.Add(Expression.Equal(
                                               selection.Table.CreateField(link.ForeignKey),
                                               src.CreateField(anchor)));
                        }
                    }
                }

                selection.Where = conditions;
                break;

            default:
                throw new DataException($"Invalid aggregate member ‘{aggregate.Member}’ because its navigation level is too deep.");
            }

            if (aggregate.Filter != null)
            {
                if (selection.Where == null)
                {
                    selection.Where = selection.Where(aggregate.Filter.Flatten(), context.Aliaser);
                }
                else
                {
                    selection.Where = ConditionExpression.And(selection.Where, selection.Where(aggregate.Filter.Flatten(), context.Aliaser));
                }
            }

            selection.Table.Alias = null;
            return(selection);
        }
Ejemplo n.º 6
0
        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);
            }
        }