private static object GetParameterValue(object data, SchemaMember member, DbType?dbType) { if (data is IModel model) { if (model.HasChanges(member.Name)) { return(member.Token.GetValue(data, dbType.HasValue ? Utility.FromDbType(dbType.Value) : null)); } else { return(((IDataEntitySimplexProperty)member.Token.Property).DefaultValue); } } if (data is IDataDictionary dictionary) { if (dictionary.HasChanges(member.Name)) { return(member.Token.GetValue(data, dbType.HasValue ? Utility.FromDbType(dbType.Value) : null)); } else { return(((IDataEntitySimplexProperty)member.Token.Property).DefaultValue); } } return(member.Token.GetValue(data, dbType.HasValue ? Utility.FromDbType(dbType.Value) : null)); }
private void Join(DeleteStatement statement, TableIdentifier table, SchemaMember schema) { if (table == null || schema == null || schema.Token.Property.IsSimplex) { return; } 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 static bool TryGetParameterValue(object data, SchemaMember member, DbType?dbType, out object value) { value = null; //尝试递归解析当前成员对应的所属数据 data = Recursive(data, member); if (data is IModel model) { if (model.HasChanges(member.Name)) { value = member.Token.GetValue(data, dbType.HasValue ? Utility.FromDbType(dbType.Value) : null); return(true); } return(false); } if (data is IDataDictionary dictionary) { if (dictionary.HasChanges(member.Name)) { value = member.Token.GetValue(data, dbType.HasValue ? Utility.FromDbType(dbType.Value) : null); return(true); } return(false); } value = member.Token.GetValue(data, dbType.HasValue ? Utility.FromDbType(dbType.Value) : null); return(true);
private TableIdentifier Join(Aliaser aliaser, UpdateStatement statement, SchemaMember schema) { if (schema == null || schema.Token.Property.IsSimplex) { return(null); } //获取关联的源 ISource source = schema.Parent == null ? statement.Table : statement.From.Get(schema.Path); //第一步:处理模式成员所在的继承实体的关联 if (schema.Ancestors != null) { foreach (var ancestor in schema.Ancestors) { source = statement.Join(aliaser, source, ancestor, schema.FullPath); } } //第二步:处理模式成员(导航属性)的关联 var join = statement.Join(aliaser, source, schema); var target = (TableIdentifier)join.Target; statement.Tables.Add(target); //返回关联的目标表 return(target); }
static object Recursive(object data, SchemaMember member) { if (data == null || member == null || member.Parent == null || member.Parent.Token.IsMultiple) { return(data); } var stack = new Stack <SchemaMember>(); while (member.Parent != null) { stack.Push(member.Parent); member = member.Parent; } while (stack.Count > 0) { member = stack.Pop(); data = member.Token.GetValue(data); if (data == null) { return(null); } } return(data); }
public void AddMemberChildren(string Identifier, bool AutoSelect) { SchemaMember parentMem = SchemaMemberFromIdentifier(Identifier); if (parentMem == null) { throw new Exception("Error: invalid identifier"); } Hierarchy hier = parentMem.Hierarchy; if (AutoSelect) { // remove children first this.RemoveMemberChildren(Identifier); // add children set MemberChildrenSet mcs = new MemberChildrenSet(null, hier, parentMem); hier.AddMember(mcs, true); } else { for (int i = 0; i < parentMem.Children.Count; i++) { hier.AddMember(parentMem.Children[i], true); } } }
private IStatementBase BuildUpsertion(IStatementBase master, SchemaMember schema) { var complex = (IEntityComplexPropertyMetadata)schema.Token.Property; var statement = new UpsertStatement(complex.Foreign, schema); foreach (var member in schema.Children) { if (member.Token.Property.IsComplex) { continue; } var property = (IEntitySimplexPropertyMetadata)member.Token.Property; var field = statement.Table.CreateField(property); var parameter = this.IsLinked(complex, property) ? Expression.Parameter(property.Name, property.Type) : Expression.Parameter(ParameterExpression.Anonymous, member, field); //设置参数的默认值 parameter.Value = property.Value; statement.Fields.Add(field); statement.Values.Add(parameter); statement.Parameters.Add(parameter); } //将新建的语句加入到主语句的从属集中 master.Slaves.Add(statement); return(statement); }
/// <inheritdoc /> public JoinClause Join(Aliaser aliaser, ISource source, SchemaMember schema) { if (schema.Token.Property.IsSimplex) { return(null); } return(this.Join(aliaser, source, (IDataEntityComplexProperty)schema.Token.Property, schema.FullPath)); }
public void CloseMember(string Identifier) { SchemaMember mem = SchemaMemberFromIdentifier(Identifier); if (mem == null) { throw new Exception("Error: invalid identifier"); } mem.Close(); }
public ParameterExpression(FieldIdentifier field, SchemaMember schema) { this.Name = Anonymous; this.Schema = schema; this.Field = field ?? throw new ArgumentNullException(nameof(field)); this.Direction = ParameterDirection.Input; if (field.Token.Property.IsSimplex) { this.DbType = ((Metadata.IDataEntitySimplexProperty)field.Token.Property).Type; } }
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 void AddSelCalcMeasureWithChildren(SchemaMember smem) { if (smem.IsPlaceholder == false) { selRatioMeasure.Items.Add(smem.Name); selCalcMeasure1.Items.Add(smem.Name); selCalcMeasure2.Items.Add(smem.Name); } // recursion on children foreach (SchemaMember child in smem.Children) { AddSelCalcMeasureWithChildren(child); } }
public void AddHierarchyChildren(string UniqueName) { Hierarchy hier = _report.Schema.Hierarchies[UniqueName]; if (hier == null) { throw new Exception("Error: invalid identifier"); } for (int i = 0; i < hier.SchemaMembers.Count; i++) { SchemaMember smem = hier.SchemaMembers[i]; hier.AddMember(smem, true); } }
private void AddMembers(Hierarchy hier, System.Collections.Specialized.StringCollection UniqueNames, SortedList ReAddDataMembers) { bool isAggr = (hier.Axis.Ordinal == 2 && hier.FilterMember is MembersAggregate?true:false); for (int i = 0; i < UniqueNames.Count; i++) { if (isAggr && UniqueNames[i] == hier.FilterMember.UniqueName) { continue; } // add if (isAggr) { // check readd or from schema Member mem = (Member)ReAddDataMembers[UniqueNames[i]]; if (mem != null) { ((MembersAggregate)hier.FilterMember).AddMember(mem); } else { SchemaMember smem = hier.SchemaMembers.Find(UniqueNames[i]); if (smem != null) { ((MembersAggregate)hier.FilterMember).AddMember(smem); } } } else { // check readd or nfrom schema Member mem = (Member)ReAddDataMembers[UniqueNames[i]]; if (mem != null) { hier.AddMember(mem, true); } else { SchemaMember smem = hier.SchemaMembers.Find(UniqueNames[i]); if (smem != null) { hier.AddMember(smem, true); } } } } }
public ParameterExpression(string name, SchemaMember schema, FieldIdentifier field) { if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } this.Name = name; this.Schema = schema; this.Field = field ?? throw new ArgumentNullException(nameof(field)); this.Direction = ParameterDirection.Input; if (field.Token.Property.IsSimplex) { this.DbType = ((Metadata.IEntitySimplexPropertyMetadata)field.Token.Property).Type; } }
public ParameterExpression(FieldIdentifier field, SchemaMember schema, object value) { this.Name = Anonymous; this.Schema = schema; this.Field = field ?? throw new ArgumentNullException(nameof(field)); this.Direction = ParameterDirection.Input; /* * 注意:更新Value属性会导致 HasValue 属性值为真! * 而 HasValue 为真的参数可能会在写入操作的参数绑定中被忽略。 */ this.Value = value; if (field.Token.Property.IsSimplex) { this.DbType = ((Metadata.IDataEntitySimplexProperty)field.Token.Property).Type; } }
private bool IsLinked(SchemaMember owner, IDataEntitySimplexProperty property) { if (owner == null || owner.Token.Property.IsSimplex) { return(false); } var links = ((IDataEntityComplexProperty)owner.Token.Property).Links; for (int i = 0; i < links.Length; i++) { if (object.Equals(links[i].Foreign, property)) { return(true); } } return(false); }
private void RecursiveRemoveMembers(SchemaMembers smems, bool isAggr, ref SortedList ReAddDataMembers) { for (int i = 0; i < smems.Count; i++) { SchemaMember smem = smems[i]; // attempt to remove if (isAggr) { if (smem.UniqueName != smem.Hierarchy.FilterMember.UniqueName) { MembersAggregate filtMem = (MembersAggregate)smem.Hierarchy.FilterMember; // check if readd Member mem = (Member)filtMem.Members[smem.UniqueName]; if (mem != null) { ReAddDataMembers.Add(mem.UniqueName, mem); } //remove filtMem.RemoveMember(smem.UniqueName); } } else { // check if readd Member mem = smem.Hierarchy.DataMembers[smem.UniqueName]; if (mem != null) { ReAddDataMembers.Add(mem.UniqueName, mem); } //remove smem.Hierarchy.RemoveMember(smem); } if (smem.IsOpen) { this.RecursiveRemoveMembers(smem.Children, isAggr, ref ReAddDataMembers); } } }
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); }
private LinkToken[] GetLinkTokens(object data, SchemaMember member) { if (member == null || member.Token.Property.IsSimplex) { return(Array.Empty <LinkToken>()); } var complex = (IDataEntityComplexProperty)member.Token.Property; var tokens = new LinkToken[complex.Links.Length]; for (int i = 0; i < complex.Links.Length; i++) { var link = complex.Links[i]; var anchors = link.GetAnchors(); if (anchors.Length > 1) { throw new DataException($"The '{member.FullPath}' multi-level link anchors are not supported in mutate operation."); } if (Utility.TryGetMemberValue(ref data, anchors[0].Name, out var value))
public void RemoveMemberChildren(string Identifier) { SchemaMember parentMem = SchemaMemberFromIdentifier(Identifier); if (parentMem == null) { throw new Exception("Error: invalid identifier"); } // check if autoselect MemberChildrenSet mcs = parentMem.Hierarchy.CalculatedMembers.GetMemberChildrenSet(parentMem.UniqueName); if (mcs != null) { parentMem.Hierarchy.RemoveMember(mcs); } else { parentMem.Hierarchy.RemoveSchemaMemberChildren(parentMem); } }
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 Initialize(string name) { this._solveOrder = -500; if (this.Member.Hierarchy != this.Hierarchy) { throw new InvalidMemberException("Hierarchy mismatch"); } if (this.Member.ChildCount <= 0) { throw new InvalidMemberException("Member has no children: " + this.Member.UniqueName); } // check if it's placeholder SchemaMember smem = this.Member as SchemaMember; if (smem != null && smem.IsPlaceholder) { throw new InvalidMemberException("'Children' function cannot be applied to placehodler member: " + this.Member.UniqueName); } this.AssignName(name); }
/// <summary> /// 创建一个参数表达式。 /// </summary> /// <param name="name">指定的参数名,如果为问号,则表示该参数将由所属参数集自动命名。</param> /// <param name="schema">指定的参数对应的模式。</param> /// <param name="field">指定参数关联的字段标识。</param> /// <returns>返回新建的参数表达式。</returns> public static ParameterExpression Parameter(string name, SchemaMember schema, FieldIdentifier field) { return(new ParameterExpression(name, schema, field)); }
public SchemaMembers GetMemberChildren(Hierarchy hier, string UniqueName, bool IfLeafAddItself) { SchemaMember smem=new SchemaMember(hier); System.Xml.XmlElement parentEl=GetMemberChildren(UniqueName, IfLeafAddItself); smem.LoadChildrenFromXmlSchema(parentEl); return smem.Children; }
public void Remove(System.Collections.Specialized.StringCollection Identifiers) { ArrayList memList = new ArrayList(); for (int i = 0; i < Identifiers.Count; i++) { short axisOrdinal = -1; int pos = -1; int mpos = -1; this.CellsetPositionFromIdentifier(Identifiers[i], ref axisOrdinal, ref pos, ref mpos); CellsetMember cstMem = _report.Cellset.GetCellsetMember((byte)axisOrdinal, mpos, pos); memList.Add(cstMem); } // remove members System.Collections.Specialized.StringCollection parentList = new System.Collections.Specialized.StringCollection(); for (int i = 0; i < memList.Count; i++) { CellsetMember cstMem = (CellsetMember)memList[i]; Hierarchy hier = _report.Schema.GetHierarchyFromMemberUniqueName(cstMem.UniqueName); // get member, remove if exisits DataMember dmem = (DataMember)hier.GetMember(cstMem.UniqueName); if (dmem != null) { dmem.Hierarchy.RemoveMember(dmem); continue; } // if not found by unique name, check if member was part of MemberChildrenSet (autoselect), // in this case we convert it to not-autoselect if (cstMem.LevelDepth == 0) { continue; } SchemaMember parentMem = _report.Schema.GetMemberParent(hier, cstMem.UniqueName); if (parentMem != null) { if (parentList.Contains(parentMem.UniqueName)) { continue; // parent already handled } parentList.Add(parentMem.UniqueName); MemberChildrenSet mcs = hier.CalculatedMembers.GetMemberChildrenSet(parentMem.UniqueName); if (mcs != null) { // add children hier.RemoveMember(mcs); hier.AddMemberChildren(parentMem.UniqueName, false); } } } // finally remove members for (int i = 0; i < memList.Count; i++) { CellsetMember cstMem = (CellsetMember)memList[i]; Hierarchy hier = _report.Schema.GetHierarchyFromMemberUniqueName(cstMem.UniqueName); hier.DataMembers.Remove(cstMem.UniqueName); } }
public void AddMembersAndRemoveSiblings(System.Collections.Specialized.StringCollection UniqueNames, bool MultiSelect) { if (MultiSelect) { for (int j = 0; j < _report.Axes.Count; j++) { for (int i = 0; i < _report.Axes[j].Hierarchies.Count; i++) { Hierarchy hier = _report.Axes[j].Hierarchies[i]; if (hier.IsOpen) { bool IsAggregateHierarchy = (hier.Axis.Ordinal == 2 && hier.FilterMember is MembersAggregate?true:false); //only aggregate can be multi-selected if (IsAggregateHierarchy == false && hier.Axis.Ordinal == 2) { continue; //beacuse if MultiSelect memebrs are not applicable to non-aggr hier on filter } // AddMembersAndRemoveSiblings(hier.SchemaMembers, UniqueNames , IsAggregateHierarchy); //it's not filter OR aggr hier on filter // deal with schema members SortedList reAddMembers = new SortedList(); this.RecursiveRemoveMembers(hier.SchemaMembers, IsAggregateHierarchy, ref reAddMembers); this.AddMembers(hier, UniqueNames, reAddMembers); // deal with calc members if (IsAggregateHierarchy) { MembersAggregate maggr = hier.FilterMember as MembersAggregate; if (maggr != null) { for (int n = 0; n < maggr.Members.Count; n++) { if (UniqueNames.Contains(maggr.Members[n].UniqueName) == false) { maggr.Members.RemoveAt(n); n--; } } } } else { for (int n = 0; n < hier.CalculatedMembers.Count; n++) { if (UniqueNames.Contains(hier.CalculatedMembers[n].UniqueName) == false) { hier.CalculatedMembers.RemoveAt(n); n--; } } } } } } } else { // axis2 // UniqueNames are actually Identifiers for (int i = 0; i < UniqueNames.Count; i++) { SchemaMember mem = this.SchemaMemberFromIdentifier(UniqueNames[i]); if (mem != null) { mem.Hierarchy.AddMember(mem, true); } } } }
public SchemaMember GetMemberParent(Hierarchy hier, string MemUniqueName) { System.Xml.XmlElement parentEl=GetMemberParent(hier.UniqueName, MemUniqueName); XmlElement memEl=(XmlElement)parentEl.FirstChild; if(memEl!=null) { SchemaMember smem=new SchemaMember(hier); smem.LoadFromXml(memEl); return smem; } return null; }
private SchemaMember LoadMemberFromXmlSchema(System.Xml.XmlElement xmlEl , int InsertIndex) { SchemaMember mem=new SchemaMember(this); mem.LoadFromXmlSchema(xmlEl); if(InsertIndex>=0) this.SchemaMembers.Insert(InsertIndex , mem, false); else this.SchemaMembers.Add(mem, false); return mem; }
private void AddSelCalcMeasureWithChildren(SchemaMember smem) { if(smem.IsPlaceholder==false) { selRatioMeasure.Items.Add(smem.Name); selCalcMeasure1.Items.Add(smem.Name); selCalcMeasure2.Items.Add(smem.Name); } // recursion on children foreach(SchemaMember child in smem.Children) AddSelCalcMeasureWithChildren(child); }
public UpsertStatement(IDataEntity entity, SchemaMember schema) : base(entity, schema, "TAR") { this.Fields = new List <FieldIdentifier>(); this.Values = new List <IExpression>(); this.Updation = new List <FieldValue>(); }
public InsertStatement(IEntityMetadata entity, SchemaMember schema) : base(entity) { this.Schema = schema; this.Fields = new List <FieldIdentifier>(); this.Values = new List <IExpression>(); }
internal static IEnumerable <UpsertStatement> BuildUpserts(IDataMutateContextBase context, IDataEntity entity, object data, SchemaMember owner, IEnumerable <SchemaMember> schemas) { var inherits = entity.GetInherits(); foreach (var inherit in inherits) { var statement = new UpsertStatement(inherit, owner); foreach (var schema in schemas) { if (!inherit.Properties.Contains(schema.Name)) { continue; } if (schema.Token.Property.IsSimplex) { var simplex = (IDataEntitySimplexProperty)schema.Token.Property; if (simplex.Sequence != null && simplex.Sequence.IsBuiltin) { statement.Sequence = new SelectStatement(owner?.FullPath); statement.Sequence.Select.Members.Add(SequenceExpression.Current(simplex.Sequence.Name, simplex.Name)); } else { //确认当前成员是否有提供的写入值 var provided = context.Validate(DataAccessMethod.Insert, simplex, out var value); var field = statement.Table.CreateField(schema.Token); statement.Fields.Add(field); var parameter = Utility.IsLinked(owner, simplex) ? ( provided ? Expression.Parameter(schema.Token.Property.Name, simplex.Type, value) : Expression.Parameter(schema.Token.Property.Name, simplex.Type) ) : ( provided ? Expression.Parameter(field, schema, value) : Expression.Parameter(field, schema) ); statement.Values.Add(parameter); statement.Parameters.Add(parameter); //处理完新增子句部分,接着再处理修改子句部分 if (!simplex.IsPrimaryKey && !simplex.Immutable && Utility.IsGenerateRequired(ref data, schema.Name)) { //确认当前成员是否有提供的写入值 if (context.Validate(DataAccessMethod.Update, simplex, out value)) { parameter = Expression.Parameter(field, schema, value); statement.Parameters.Add(parameter); } //如果当前的数据成员类型为递增步长类型则生成递增表达式 if (schema.Token.MemberType == typeof(Interval)) { /* * 注:默认参数类型为对应字段的类型,而该字段类型可能为无符号整数, * 因此当参数类型为无符号整数并且步长为负数(递减),则可能导致参数类型转换溢出, * 所以必须将该参数类型重置为有符号整数(32位整数)。 */ parameter.DbType = System.Data.DbType.Int32; //字段设置项的值为字段加参数的加法表达式 statement.Updation.Add(new FieldValue(field, field.Add(parameter))); } else { statement.Updation.Add(new FieldValue(field, parameter)); } } } } else { //不可变复合属性不支持任何写操作,即在修改操作中不能包含不可变复合属性 if (schema.Token.Property.Immutable) { throw new DataException($"The '{schema.FullPath}' is an immutable complex(navigation) property and does not support the upsert operation."); } if (!schema.HasChildren) { throw new DataException($"Missing members that does not specify '{schema.FullPath}' complex property."); } var complex = (IDataEntityComplexProperty)schema.Token.Property; var slaves = BuildUpserts( context, complex.Foreign, null, schema, schema.Children); foreach (var slave in slaves) { slave.Schema = schema; statement.Slaves.Add(slave); } } } if (statement.Fields.Count > 0) { yield return(statement); } } }
public SchemaMembers GetSchemaMembers(Hierarchy hier, string[] UniqueNames) { System.Xml.XmlElement parentEl=GetSchemaMembers(UniqueNames); SchemaMembers smems=new SchemaMembers(hier, null); foreach(System.Xml.XmlElement childEl in parentEl.ChildNodes) { SchemaMember child=new SchemaMember(hier); child.LoadFromXmlSchema(childEl); smems.Add(child, false); } return smems; }
public SchemaMembers GetMemberParentWithSiblings(Hierarchy hier, string MemUniqueName) { SchemaMember smem=new SchemaMember(hier); System.Xml.XmlElement parentEl=GetMemberParentWithSiblings(hier.UniqueName, MemUniqueName); smem.LoadChildrenFromXmlSchema(parentEl); return smem.Children; }
protected MutateStatement(IDataEntity entity, SchemaMember schema = null, string alias = "T") : base(entity, alias) { this.Schema = schema; }
public void RemoveSchemaMemberChildren(SchemaMember smem) { for(int i=0;i<smem.Children.Count;i++) this.DataMembers.Remove(smem.Children[i].UniqueName); }