protected virtual IExpression VisitTable(TableIdentifier table) { if (table.IsTemporary) { _output.Append(table.Name); } else { _output.Append(this.GetIdentifier(table.Name)); } if (!string.IsNullOrEmpty(table.Alias) && !string.Equals(table.Name, table.Alias)) { _output.Append(" AS " + table.Alias); } return(table); }
public static ISource From(this IStatement statement, TableIdentifier origin, string memberPath, Func<ISource, IDataEntityComplexProperty, ISource> subqueryFactory, out IDataEntityProperty property) { var found = origin.Reduce(memberPath, ctx => { var source = ctx.Source; if(ctx.Ancestors != null) { foreach(var ancestor in ctx.Ancestors) { source = statement.Join(source, ancestor, ctx.Path); } } if(ctx.Property.IsComplex) { var complex = (IDataEntityComplexProperty)ctx.Property; if(complex.Multiplicity == DataAssociationMultiplicity.Many) { if(subqueryFactory != null) return subqueryFactory(source, complex); //如果不允许一对多的子查询则抛出异常 throw new DataException($"The specified '{ctx.FullPath}' member is a one-to-many composite(navigation) property that cannot appear in the sorting and specific condition clauses."); } source = statement.Join(source, complex, ctx.FullPath); } return source; }); if(found.IsFailed) throw new DataException($"The specified '{memberPath}' member does not exist in the '{origin.Entity?.Name}' entity and it's inherits."); //输出找到的属性元素 property = found.Property; //返回找到的源 return found.Source; }
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 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); } } } }
/// <summary> /// <para>从指定的表标识对应的实体开始进行路径展开。</para> /// <para>注:展开过程包括对父实体的属性集的搜索。</para> /// </summary> /// <param name="table">指定的进行展开的起点。</param> /// <param name="path">指定要展开的成员路径,支持多级导航属性路径。</param> /// <param name="step">指定路径中每个属性的展开回调函数。</param> /// <returns>返回找到的结果。</returns> public static ReduceResult Reduce(this TableIdentifier table, string path, Func <ReduceContext, ISource> step = null) { if (table == null) { throw new ArgumentNullException(nameof(table)); } if (table.Entity == null) { throw new DataException($"The '{table}' table cannot be expanded."); } if (string.IsNullOrEmpty(path)) { return(ReduceResult.Failure(table)); } ICollection <IEntityMetadata> ancestors = null; IEntityPropertyMetadata property = null; ISource token = table; var parts = path.Split('.'); var properties = table.Entity.Properties; for (int i = 0; i < parts.Length; i++) { if (properties == null) { return(ReduceResult.Failure(token)); } //如果当前属性集合中不包含指定的属性,则尝试从父实体中查找 if (!properties.TryGet(parts[i], out property)) { //尝试从父实体中查找指定的属性 property = FindBaseProperty(ref properties, parts[i], ref ancestors); //如果父实体中也不含指定的属性则返回失败 if (property == null) { return(ReduceResult.Failure(token)); } } //如果回调函数不为空,则调用匹配回调函数 //注意:将回调函数返回的结果作为下一次的用户数据保存起来 if (step != null) { token = step(new ReduceContext(string.Join(".", parts, 0, i), token, property, ancestors)); } //清空继承实体链 if (ancestors != null) { ancestors.Clear(); } if (property.IsSimplex) { break; } else { properties = GetAssociatedProperties((IEntityComplexPropertyMetadata)property, ref ancestors); } } //返回查找到的结果 return(new ReduceResult(token, property)); }
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); } } } } }
protected StatementBase(TableIdentifier table) { this.Table = table ?? throw new ArgumentNullException(nameof(table)); }
public SubqueryStatement(IStatementBase host, TableIdentifier table) : base(table) { this.Host = host ?? throw new ArgumentNullException(nameof(host)); }
public ISelectStatementBase Subquery(TableIdentifier table) { return(new SubqueryStatement(this, table)); }
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); } } } }
private IEnumerable <JoinClause> Join(Aliaser aliaser, DeleteStatement statement, TableIdentifier table, string fullPath = null) { if (table == null || table.Entity == null) { yield break; } var super = table.Entity.GetBaseEntity(); while (super != null) { var clause = JoinClause.Create(table, fullPath, name => statement.From.TryGet(name, out var join) ? (JoinClause)join : null, entity => new TableIdentifier(entity, aliaser.Generate())); if (!statement.From.Contains(clause)) { statement.From.Add(clause); statement.Tables.Add((TableIdentifier)clause.Target); } super = super.GetBaseEntity(); yield return(clause); } }