private void HandleEntitySetElement(XmlReader reader) { DebugCheck.NotNull(reader); var set = new EntityContainerEntitySet(this); set.Parse(reader); Members.Add(set, true, Strings.DuplicateEntityContainerMemberName); }
internal override SchemaElement Clone(SchemaElement parentElement) { var entitySet = new EntityContainerEntitySet((EntityContainer)parentElement); entitySet._definingQueryElement = _definingQueryElement; entitySet._entityType = _entityType; entitySet._schema = _schema; entitySet._table = _table; entitySet.Name = Name; return entitySet; }
/// <summary> /// Adds a child EntitySet's tableKey (Schema/Table combination) to the validation collection /// This is used to validate that no child EntitySets share a Schema.Table combination /// </summary> private void CheckForDuplicateTableMapping(HashSet <string> tableKeys, EntityContainerEntitySet entitySet) { string schema; string table; if (String.IsNullOrEmpty(entitySet.DbSchema)) { // if there is no specified DbSchema, use the parent EntityContainer's name schema = Name; } else { schema = entitySet.DbSchema; } if (String.IsNullOrEmpty(entitySet.Table)) { // if there is no specified Table, use the EntitySet's name table = entitySet.Name; } else { table = entitySet.Table; } // create a key using the DbSchema and Table var tableKey = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", schema, table); if (entitySet.DefiningQuery != null) { // don't consider the schema name for defining queries, because // we can't say for sure that it is the same as the entity container // so in this example // // <EntityContainer Name="dbo"> // <EntitySet Name="ByVal"> // <DefiningQuery>Select col1 from dbi.ByVal</DefiningQuery> // </EntitySet> // <EntitySet Name="ByVal1" Table="ByVal"/> // ... // // ByVal and ByVal1 should not conflict in our check tableKey = entitySet.Name; } var alreadyExisted = !tableKeys.Add(tableKey); if (alreadyExisted) { entitySet.AddError( ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, Strings.DuplicateEntitySetTable(entitySet.Name, schema, table)); } }
/// <summary> /// Used during the resolve phase to resolve the type name to the object that represents that type /// </summary> internal override void ResolveTopLevelNames() { base.ResolveTopLevelNames(); if (_entitySet == null) { _entitySet = ParentElement.ParentElement.FindEntitySet(_unresolvedEntitySetName); if (_entitySet == null) { AddError( ErrorCode.InvalidEndEntitySet, EdmSchemaErrorSeverity.Error, Strings.InvalidEntitySetNameReference(_unresolvedEntitySetName, Name)); } } }
/// <summary> /// Create and add a EntityContainerEnd from the IRelationshipEnd provided /// </summary> /// <param name="relationshipEnd"> The relationship end of the end to add. </param> /// <param name="entitySet"> The entitySet to associate with the relationship end. </param> protected override void AddEnd(IRelationshipEnd relationshipEnd, EntityContainerEntitySet entitySet) { DebugCheck.NotNull(relationshipEnd); Debug.Assert(!_relationshipEnds.ContainsKey(relationshipEnd.Name)); // we expect set to be null sometimes var end = new EntityContainerAssociationSetEnd(this); end.Role = relationshipEnd.Name; end.RelationshipEnd = relationshipEnd; end.EntitySet = entitySet; if (end.EntitySet != null) { _relationshipEnds.Add(end.Role, end); } }
/// <summary> /// If the role name is missing but an entity set is given, figure out what the /// relationship end should be /// </summary> /// <param name="set"> The given EntitySet </param> /// <returns> The appropriate relationship end </returns> private IRelationshipEnd InferRelationshipEnd(EntityContainerEntitySet set) { DebugCheck.NotNull(set); if (ParentElement.Relationship == null) { return(null); } var possibleEnds = new List <IRelationshipEnd>(); foreach (var end in ParentElement.Relationship.Ends) { if (set.EntityType.IsOfType(end.Type)) { possibleEnds.Add(end); } } if (possibleEnds.Count == 1) { return(possibleEnds[0]); } else if (possibleEnds.Count == 0) { // no matchs AddError( ErrorCode.FailedInference, EdmSchemaErrorSeverity.Error, Strings.InferRelationshipEndFailedNoEntitySetMatch( set.Name, ParentElement.Name, ParentElement.Relationship.FQName, set.EntityType.FQName, ParentElement.ParentElement.FQName)); } else { // ambiguous AddError( ErrorCode.FailedInference, EdmSchemaErrorSeverity.Error, Strings.InferRelationshipEndAmbiguous( set.Name, ParentElement.Name, ParentElement.Relationship.FQName, set.EntityType.FQName, ParentElement.ParentElement.FQName)); } return(null); }
private static bool TypeIsSubTypeOf( SchemaEntityType itemType, Dictionary <SchemaEntityType, EntityContainerEntitySet> baseEntitySetTypes, out EntityContainerEntitySet set) { if (itemType.IsTypeHierarchyRoot) { // can't be a sub type if we are a base type set = null; return(false); } // walk up the hierarchy looking for a base that is the base type of an entityset for (var baseType = itemType.BaseType as SchemaEntityType; baseType != null; baseType = baseType.BaseType as SchemaEntityType) { if (baseEntitySetTypes.ContainsKey(baseType)) { set = baseEntitySetTypes[baseType]; return(true); } } set = null; return(false); }
internal void ResolveEntitySet(SchemaElement owner, string unresolvedEntitySet, ref EntityContainerEntitySet entitySet) { Debug.Assert(IsFunctionImport, "Only FunctionImport elkements specify EntitySets"); Debug.Assert(null != _container, "function imports must know container"); // resolve entity set if (null == entitySet && null != unresolvedEntitySet) { entitySet = _container.FindEntitySet(unresolvedEntitySet); if (null == entitySet) { owner.AddError( ErrorCode.FunctionImportUnknownEntitySet, EdmSchemaErrorSeverity.Error, Strings.FunctionImportUnknownEntitySet(unresolvedEntitySet, FQName)); } } }
protected abstract void AddEnd(IRelationshipEnd relationshipEnd, EntityContainerEntitySet entitySet);
/// <summary> /// If the role name is missing but an entity set is given, figure out what the /// relationship end should be /// </summary> /// <param name="set">The given EntitySet</param> /// <returns>The appropriate relationship end</returns> private IRelationshipEnd InferRelationshipEnd(EntityContainerEntitySet set) { Debug.Assert(set != null, "set parameter is null"); if (ParentElement.Relationship == null) { return null; } var possibleEnds = new List<IRelationshipEnd>(); foreach (var end in ParentElement.Relationship.Ends) { if (set.EntityType.IsOfType(end.Type)) { possibleEnds.Add(end); } } if (possibleEnds.Count == 1) { return possibleEnds[0]; } else if (possibleEnds.Count == 0) { // no matchs AddError( ErrorCode.FailedInference, EdmSchemaErrorSeverity.Error, Strings.InferRelationshipEndFailedNoEntitySetMatch( set.Name, ParentElement.Name, ParentElement.Relationship.FQName, set.EntityType.FQName, ParentElement.ParentElement.FQName)); } else { // ambiguous AddError( ErrorCode.FailedInference, EdmSchemaErrorSeverity.Error, Strings.InferRelationshipEndAmbiguous( set.Name, ParentElement.Name, ParentElement.Relationship.FQName, set.EntityType.FQName, ParentElement.ParentElement.FQName)); } return null; }
/// <summary> /// Constructs an EntityContainerEntitySet /// </summary> /// <param name="parentElement"> Reference to the schema element. </param> public EntityContainerEntitySetDefiningQuery(EntityContainerEntitySet parentElement) : base(parentElement) { }
/// <summary> /// Constructs an EntityContainerEntitySet /// </summary> /// <param name="parentElement">Reference to the schema element.</param> public EntityContainerEntitySetDefiningQuery(EntityContainerEntitySet parentElement) : base(parentElement) { }
internal override SchemaElement Clone(SchemaElement parentElement) { var entitySet = new EntityContainerEntitySet((EntityContainer)parentElement); entitySet._definingQueryElement = _definingQueryElement; entitySet._entityType = _entityType; entitySet._schema = _schema; entitySet._table = _table; entitySet.Name = Name; return entitySet; }
private static bool TypeIsSubTypeOf( SchemaEntityType itemType, Dictionary<SchemaEntityType, EntityContainerEntitySet> baseEntitySetTypes, out EntityContainerEntitySet set) { if (itemType.IsTypeHierarchyRoot) { // can't be a sub type if we are a base type set = null; return false; } // walk up the hierarchy looking for a base that is the base type of an entityset for (var baseType = itemType.BaseType as SchemaEntityType; baseType != null; baseType = baseType.BaseType as SchemaEntityType) { if (baseEntitySetTypes.ContainsKey(baseType)) { set = baseEntitySetTypes[baseType]; return true; } } set = null; return false; }
/// <summary> /// Used during the resolve phase to resolve the type name to the object that represents that type /// </summary> internal override void ResolveTopLevelNames() { base.ResolveTopLevelNames(); if (_entitySet == null) { _entitySet = ParentElement.ParentElement.FindEntitySet(_unresolvedEntitySetName); if (_entitySet == null) { AddError( ErrorCode.InvalidEndEntitySet, EdmSchemaErrorSeverity.Error, Strings.InvalidEntitySetNameReference(_unresolvedEntitySetName, Name)); } } }
protected abstract void AddEnd(IRelationshipEnd relationshipEnd, EntityContainerEntitySet entitySet);
/// <summary> /// Create and add a EntityContainerEnd from the IRelationshipEnd provided /// </summary> /// <param name="relationshipEnd"> The relationship end of the end to add. </param> /// <param name="entitySet"> The entitySet to associate with the relationship end. </param> protected override void AddEnd(IRelationshipEnd relationshipEnd, EntityContainerEntitySet entitySet) { Debug.Assert(relationshipEnd != null); Debug.Assert(!_relationshipEnds.ContainsKey(relationshipEnd.Name)); // we expect set to be null sometimes var end = new EntityContainerAssociationSetEnd(this); end.Role = relationshipEnd.Name; end.RelationshipEnd = relationshipEnd; end.EntitySet = entitySet; if (end.EntitySet != null) { _relationshipEnds.Add(end.Role, end); } }
/// <summary> /// validate the following negative scenarios: /// ReturnType="Collection(EntityTypeA)" /// ReturnType="Collection(EntityTypeA)" EntitySet="ESet.EType is not oftype EntityTypeA" /// EntitySet="A" /// ReturnType="Collection(ComplexTypeA)" EntitySet="something" /// ReturnType="Collection(ComplexTypeA)", but the ComplexTypeA has a nested complexType property, this scenario will be handle in the runtime /// </summary> private void ValidateFunctionImportReturnType( SchemaElement owner, SchemaType returnType, EntityContainerEntitySet entitySet, bool entitySetPathDefined) { // If entity type, verify specification of entity set and that the type is appropriate for the entity set var entityType = returnType as SchemaEntityType; if (entitySet != null && entitySetPathDefined) { owner.AddError( ErrorCode.FunctionImportEntitySetAndEntitySetPathDeclared, EdmSchemaErrorSeverity.Error, Strings.FunctionImportEntitySetAndEntitySetPathDeclared(FQName)); } if (null != entityType) { // entity type if (null == entitySet) { // ReturnType="Collection(EntityTypeA)" owner.AddError( ErrorCode.FunctionImportReturnsEntitiesButDoesNotSpecifyEntitySet, EdmSchemaErrorSeverity.Error, Strings.FunctionImportReturnEntitiesButDoesNotSpecifyEntitySet(FQName)); } else if (null != entitySet.EntityType && !entityType.IsOfType(entitySet.EntityType)) { // ReturnType="Collection(EntityTypeA)" EntitySet="ESet.EType is not oftype EntityTypeA" owner.AddError( ErrorCode.FunctionImportEntityTypeDoesNotMatchEntitySet, EdmSchemaErrorSeverity.Error, Strings.FunctionImportEntityTypeDoesNotMatchEntitySet( FQName, entitySet.EntityType.FQName, entitySet.Name)); } } else { // complex type var complexType = returnType as SchemaComplexType; if (complexType != null) { if (entitySet != null || entitySetPathDefined) { // ReturnType="Collection(ComplexTypeA)" EntitySet="something" owner.AddError( ErrorCode.ComplexTypeAsReturnTypeAndDefinedEntitySet, EdmSchemaErrorSeverity.Error, owner.LineNumber, owner.LinePosition, Strings.ComplexTypeAsReturnTypeAndDefinedEntitySet(FQName, complexType.Name)); } } else { Debug.Assert( returnType == null || returnType is ScalarType || returnType is SchemaEnumType || returnType is Relationship, "null return type, scalar return type, enum return type or relationship expected here."); // scalar type or no return type if (entitySet != null || entitySetPathDefined) { // EntitySet="A" owner.AddError( ErrorCode.FunctionImportSpecifiesEntitySetButDoesNotReturnEntityType, EdmSchemaErrorSeverity.Error, Strings.FunctionImportSpecifiesEntitySetButNotEntityType(FQName)); } } } }
private void ValidateFunctionImportReturnType( SchemaElement owner, SchemaType returnType, CollectionKind returnTypeCollectionKind, EntityContainerEntitySet entitySet, bool entitySetPathDefined) { if (returnType != null && !ReturnTypeMeetsFunctionImportBasicRequirements(returnType, returnTypeCollectionKind)) { owner.AddError( ErrorCode.FunctionImportUnsupportedReturnType, EdmSchemaErrorSeverity.Error, owner, GetReturnTypeErrorMessage(Name) ); } ValidateFunctionImportReturnType(owner, returnType, entitySet, entitySetPathDefined); }
internal void ResolveEntitySet(SchemaElement owner, string unresolvedEntitySet, ref EntityContainerEntitySet entitySet) { Debug.Assert(IsFunctionImport, "Only FunctionImport elkements specify EntitySets"); Debug.Assert(null != _container, "function imports must know container"); // resolve entity set if (null == entitySet && null != unresolvedEntitySet) { entitySet = _container.FindEntitySet(unresolvedEntitySet); if (null == entitySet) { owner.AddError( ErrorCode.FunctionImportUnknownEntitySet, EdmSchemaErrorSeverity.Error, Strings.FunctionImportUnknownEntitySet(unresolvedEntitySet, FQName)); } } }
private void HandleEntitySetElement(XmlReader reader) { DebugCheck.NotNull(reader); var set = new EntityContainerEntitySet(this); set.Parse(reader); Members.Add(set, true, Strings.DuplicateEntityContainerMemberName); }
private void ValidateFunctionImportReturnType( SchemaElement owner, SchemaType returnType, CollectionKind returnTypeCollectionKind, EntityContainerEntitySet entitySet, bool entitySetPathDefined) { if (returnType != null && !ReturnTypeMeetsFunctionImportBasicRequirements(returnType, returnTypeCollectionKind)) { owner.AddError( ErrorCode.FunctionImportUnsupportedReturnType, EdmSchemaErrorSeverity.Error, owner, GetReturnTypeErrorMessage(Name) ); } ValidateFunctionImportReturnType(owner, returnType, entitySet, entitySetPathDefined); }
/// <summary> /// Adds a child EntitySet's tableKey (Schema/Table combination) to the validation collection /// This is used to validate that no child EntitySets share a Schema.Table combination /// </summary> private void CheckForDuplicateTableMapping(HashSet<string> tableKeys, EntityContainerEntitySet entitySet) { string schema; string table; if (String.IsNullOrEmpty(entitySet.DbSchema)) { // if there is no specified DbSchema, use the parent EntityContainer's name schema = Name; } else { schema = entitySet.DbSchema; } if (String.IsNullOrEmpty(entitySet.Table)) { // if there is no specified Table, use the EntitySet's name table = entitySet.Name; } else { table = entitySet.Table; } // create a key using the DbSchema and Table var tableKey = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", schema, table); if (entitySet.DefiningQuery != null) { // don't consider the schema name for defining queries, because // we can't say for sure that it is the same as the entity container // so in this example // // <EntityContainer Name="dbo"> // <EntitySet Name="ByVal"> // <DefiningQuery>Select col1 from dbi.ByVal</DefiningQuery> // </EntitySet> // <EntitySet Name="ByVal1" Table="ByVal"/> // ... // // ByVal and ByVal1 should not conflict in our check tableKey = entitySet.Name; } var alreadyExisted = !tableKeys.Add(tableKey); if (alreadyExisted) { entitySet.AddError( ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, Strings.DuplicateEntitySetTable(entitySet.Name, schema, table)); } }
/// <summary> /// validate the following negative scenarios: /// ReturnType="Collection(EntityTypeA)" /// ReturnType="Collection(EntityTypeA)" EntitySet="ESet.EType is not oftype EntityTypeA" /// EntitySet="A" /// ReturnType="Collection(ComplexTypeA)" EntitySet="something" /// ReturnType="Collection(ComplexTypeA)", but the ComplexTypeA has a nested complexType property, this scenario will be handle in the runtime /// </summary> private void ValidateFunctionImportReturnType( SchemaElement owner, SchemaType returnType, EntityContainerEntitySet entitySet, bool entitySetPathDefined) { // If entity type, verify specification of entity set and that the type is appropriate for the entity set var entityType = returnType as SchemaEntityType; if (entitySet != null && entitySetPathDefined) { owner.AddError( ErrorCode.FunctionImportEntitySetAndEntitySetPathDeclared, EdmSchemaErrorSeverity.Error, Strings.FunctionImportEntitySetAndEntitySetPathDeclared(FQName)); } if (null != entityType) { // entity type if (null == entitySet) { // ReturnType="Collection(EntityTypeA)" owner.AddError( ErrorCode.FunctionImportReturnsEntitiesButDoesNotSpecifyEntitySet, EdmSchemaErrorSeverity.Error, Strings.FunctionImportReturnEntitiesButDoesNotSpecifyEntitySet(FQName)); } else if (null != entitySet.EntityType && !entityType.IsOfType(entitySet.EntityType)) { // ReturnType="Collection(EntityTypeA)" EntitySet="ESet.EType is not oftype EntityTypeA" owner.AddError( ErrorCode.FunctionImportEntityTypeDoesNotMatchEntitySet, EdmSchemaErrorSeverity.Error, Strings.FunctionImportEntityTypeDoesNotMatchEntitySet( FQName, entitySet.EntityType.FQName, entitySet.Name)); } } else { // complex type var complexType = returnType as SchemaComplexType; if (complexType != null) { if (entitySet != null || entitySetPathDefined) { // ReturnType="Collection(ComplexTypeA)" EntitySet="something" owner.AddError( ErrorCode.ComplexTypeAsReturnTypeAndDefinedEntitySet, EdmSchemaErrorSeverity.Error, owner.LineNumber, owner.LinePosition, Strings.ComplexTypeAsReturnTypeAndDefinedEntitySet(FQName, complexType.Name)); } } else { Debug.Assert( returnType == null || returnType is ScalarType || returnType is SchemaEnumType || returnType is Relationship, "null return type, scalar return type, enum return type or relationship expected here."); // scalar type or no return type if (entitySet != null || entitySetPathDefined) { // EntitySet="A" owner.AddError( ErrorCode.FunctionImportSpecifiesEntitySetButDoesNotReturnEntityType, EdmSchemaErrorSeverity.Error, Strings.FunctionImportSpecifiesEntitySetButNotEntityType(FQName)); } } } }