Exemple #1
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);
                }
            }
        }
        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);
        }