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); } }
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); } }
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); }
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); } }