private static void ConvertSchema( Schema somSchema, DbProviderManifest providerManifest, Converter.ConversionCache convertedItemCache, Dictionary <SchemaElement, GlobalItem> newGlobalItems) { List <System.Data.Entity.Core.SchemaObjectModel.Function> functionList = new List <System.Data.Entity.Core.SchemaObjectModel.Function>(); foreach (System.Data.Entity.Core.SchemaObjectModel.SchemaType schemaType in somSchema.SchemaTypes) { if (Converter.LoadSchemaElement(schemaType, providerManifest, convertedItemCache, newGlobalItems) == null) { System.Data.Entity.Core.SchemaObjectModel.Function function = schemaType as System.Data.Entity.Core.SchemaObjectModel.Function; if (function != null) { functionList.Add(function); } } } foreach (SchemaEntityType element in somSchema.SchemaTypes.OfType <SchemaEntityType>()) { Converter.LoadEntityTypePhase2(element, providerManifest, convertedItemCache, newGlobalItems); } foreach (System.Data.Entity.Core.SchemaObjectModel.SchemaType element in functionList) { Converter.LoadSchemaElement(element, providerManifest, convertedItemCache, newGlobalItems); } if (convertedItemCache.ItemCollection.DataSpace == DataSpace.CSpace) { ((EdmItemCollection)convertedItemCache.ItemCollection).EdmVersion = somSchema.SchemaVersion; } else { StoreItemCollection itemCollection = convertedItemCache.ItemCollection as StoreItemCollection; if (itemCollection == null) { return; } itemCollection.StoreSchemaVersion = somSchema.SchemaVersion; } }
internal Parameter(Function parentElement) : base(parentElement) { _typeUsageBuilder = new TypeUsageBuilder(this); }
// <summary> // Constructs an FunctionCommandText // </summary> // <param name="parentElement"> Reference to the schema element. </param> public FunctionCommandText(Function parentElement) : base(parentElement) { }
internal FacetEnabledSchemaElement(Function parentElement) : base(parentElement) { }
protected void AddFunctionType(Function function) { var space = DataModel == SchemaDataModelOption.EntityDataModel ? "Conceptual" : "Storage"; if (SchemaVersion >= XmlConstants.EdmVersionForV2 && SchemaManager.SchemaTypes.ContainsKey(function.FQName)) { function.AddError( ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, Strings.AmbiguousFunctionAndType(function.FQName, space)); } else { var error = SchemaManager.SchemaTypes.TryAdd(function); Debug.Assert(error != AddErrorKind.MissingNameError, "Function identity can never be null while adding global functions"); if (error != AddErrorKind.Succeeded) { function.AddError( ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, Strings.AmbiguousFunctionOverload(function.FQName, space)); } else { SchemaTypes.Add(function); } } }
// <summary> // Handler for the Function element // </summary> // <param name="reader"> xml reader currently positioned at EntityType element </param> private void HandleFunctionElement(XmlReader reader) { DebugCheck.NotNull(reader); var function = new Function(this); function.Parse(reader); Functions.Add(function); }
protected void CloneSetFunctionFields(Function clone) { clone._isAggregate = _isAggregate; clone._isBuiltIn = _isBuiltIn; clone._isNiladicFunction = _isNiladicFunction; clone._isComposable = _isComposable; clone._commandText = _commandText; clone._storeFunctionName = _storeFunctionName; clone._type = _type; clone._returnTypeList = _returnTypeList; clone._returnTypeCollectionKind = _returnTypeCollectionKind; clone._parameterTypeSemantics = _parameterTypeSemantics; clone._schema = _schema; clone.Name = Name; // Clone all the parameters foreach (var parameter in Parameters) { var error = clone.Parameters.TryAdd((Parameter)parameter.Clone(clone)); Debug.Assert(error == AddErrorKind.Succeeded, "Since we are cloning a validated function, this should never fail."); } }
/// <summary> /// </summary> /// <param name="parentElement"> </param> internal ReturnType(Function parentElement) : base(parentElement) { _typeUsageBuilder = new TypeUsageBuilder(this); }
private static EdmFunction ConvertToFunction( Function somFunction, DbProviderManifest providerManifest, ConversionCache convertedItemCache, EntityContainer functionImportEntityContainer, Dictionary<SchemaElement, GlobalItem> newGlobalItems) { // If we already have it, don't bother converting GlobalItem globalItem = null; // if we are converted the function import, we need not check the global items collection, // since the function imports are local to the entity container if (!somFunction.IsFunctionImport && newGlobalItems.TryGetValue(somFunction, out globalItem)) { return (EdmFunction)globalItem; } var areConvertingForProviderManifest = somFunction.Schema.DataModel == SchemaDataModelOption.ProviderManifestModel; var returnParameters = new List<FunctionParameter>(); if (somFunction.ReturnTypeList != null) { var i = 0; foreach (var somReturnType in somFunction.ReturnTypeList) { var returnType = GetFunctionTypeUsage( somFunction is ModelFunction, somFunction, somReturnType, providerManifest, areConvertingForProviderManifest, somReturnType.Type, somReturnType.CollectionKind, somReturnType.IsRefType /*isRefType*/, convertedItemCache, newGlobalItems); if (null != returnType) { // Create the return parameter object, need to set the declaring type explicitly on the return parameter // because we aren't adding it to the members collection var modifier = i == 0 ? string.Empty : i.ToString(CultureInfo.InvariantCulture); i++; var returnParameter = new FunctionParameter( EdmConstants.ReturnType + modifier, returnType, ParameterMode.ReturnValue); AddOtherContent(somReturnType, returnParameter); returnParameters.Add(returnParameter); } else { return null; } } } // this case must be second to avoid calling somFunction.Type when returnTypeList has more than one element. else if (somFunction.Type != null) { var returnType = GetFunctionTypeUsage( somFunction is ModelFunction, somFunction, null, providerManifest, areConvertingForProviderManifest, somFunction.Type, somFunction.CollectionKind, somFunction.IsReturnAttributeReftype /*isRefType*/, convertedItemCache, newGlobalItems); if (null != returnType) { // Create the return parameter object, need to set the declaring type explicitly on the return parameter // because we aren't adding it to the members collection returnParameters.Add(new FunctionParameter(EdmConstants.ReturnType, returnType, ParameterMode.ReturnValue)); } else { //Return type was specified but we could not find a type usage return null; } } string functionNamespace; EntitySet[] entitySets = null; if (somFunction.IsFunctionImport) { var somFunctionImport = (FunctionImportElement)somFunction; functionNamespace = somFunctionImport.Container.Name; if (null != somFunctionImport.EntitySet) { EntityContainer entityContainer; Debug.Assert( somFunctionImport.ReturnTypeList == null || somFunctionImport.ReturnTypeList.Count == 1, "EntitySet cannot be specified on a FunctionImport if there are multiple ReturnType children"); Debug.Assert( functionImportEntityContainer != null, "functionImportEntityContainer must be specified during function import conversion"); entityContainer = functionImportEntityContainer; entitySets = new[] { GetEntitySet(somFunctionImport.EntitySet, entityContainer) }; } else if (null != somFunctionImport.ReturnTypeList) { Debug.Assert( functionImportEntityContainer != null, "functionImportEntityContainer must be specified during function import conversion"); var entityContainer = functionImportEntityContainer; entitySets = somFunctionImport.ReturnTypeList .Select( returnType => null != returnType.EntitySet ? GetEntitySet(returnType.EntitySet, functionImportEntityContainer) : null) .ToArray(); } } else { functionNamespace = somFunction.Namespace; } var parameters = new List<FunctionParameter>(); foreach (var somParameter in somFunction.Parameters) { var parameterType = GetFunctionTypeUsage( somFunction is ModelFunction, somFunction, somParameter, providerManifest, areConvertingForProviderManifest, somParameter.Type, somParameter.CollectionKind, somParameter.IsRefType, convertedItemCache, newGlobalItems); if (parameterType == null) { return null; } var parameter = new FunctionParameter( somParameter.Name, parameterType, GetParameterMode(somParameter.ParameterDirection)); AddOtherContent(somParameter, parameter); if (somParameter.Documentation != null) { parameter.Documentation = ConvertToDocumentation(somParameter.Documentation); } parameters.Add(parameter); } var function = new EdmFunction( somFunction.Name, functionNamespace, GetDataSpace(providerManifest), new EdmFunctionPayload { Schema = somFunction.DbSchema, StoreFunctionName = somFunction.StoreFunctionName, CommandText = somFunction.CommandText, EntitySets = entitySets, IsAggregate = somFunction.IsAggregate, IsBuiltIn = somFunction.IsBuiltIn, IsNiladic = somFunction.IsNiladicFunction, IsComposable = somFunction.IsComposable, IsFromProviderManifest = areConvertingForProviderManifest, IsFunctionImport = somFunction.IsFunctionImport, ReturnParameters = returnParameters.ToArray(), Parameters = parameters.ToArray(), ParameterTypeSemantics = somFunction.ParameterTypeSemantics, }); // Add this function to new global items, only if it is not a function import if (!somFunction.IsFunctionImport) { newGlobalItems.Add(somFunction, function); } //Check if we already converted functions since we are loading it from //ssdl we could see functions many times. GlobalItem returnFunction = null; Debug.Assert( !convertedItemCache.ItemCollection.TryGetValue(function.Identity, false, out returnFunction), "Function duplicates must be checked by som"); // Extract the optional Documentation if (somFunction.Documentation != null) { function.Documentation = ConvertToDocumentation(somFunction.Documentation); } AddOtherContent(somFunction, function); return function; }
private static TypeUsage GetFunctionTypeUsage( bool isModelFunction, Function somFunction, FacetEnabledSchemaElement somParameter, DbProviderManifest providerManifest, bool areConvertingForProviderManifest, SchemaType type, CollectionKind collectionKind, bool isRefType, ConversionCache convertedItemCache, Dictionary<SchemaElement, GlobalItem> newGlobalItems) { if (null != somParameter && areConvertingForProviderManifest && somParameter.HasUserDefinedFacets) { return somParameter.TypeUsage; } if (null == type) { if (isModelFunction && somParameter != null && somParameter is Parameter) { ((Parameter)somParameter).ResolveNestedTypeNames(convertedItemCache, newGlobalItems); return somParameter.TypeUsage; } else if (somParameter != null && somParameter is ReturnType) { ((ReturnType)somParameter).ResolveNestedTypeNames(convertedItemCache, newGlobalItems); return somParameter.TypeUsage; } else { return null; } } EdmType edmType; if (!areConvertingForProviderManifest) { // SOM verifies the type is either scalar, row, or entity var scalarType = type as ScalarType; if (null != scalarType) { if (isModelFunction && somParameter != null) { if (somParameter.TypeUsage == null) { somParameter.ValidateAndSetTypeUsage(scalarType); } return somParameter.TypeUsage; } else if (isModelFunction) { var modelFunction = somFunction as ModelFunction; if (modelFunction.TypeUsage == null) { modelFunction.ValidateAndSetTypeUsage(scalarType); } return modelFunction.TypeUsage; } else if (somParameter != null && somParameter.HasUserDefinedFacets && somFunction.Schema.DataModel == SchemaDataModelOption.ProviderDataModel) { somParameter.ValidateAndSetTypeUsage(scalarType); return somParameter.TypeUsage; } else { edmType = GetPrimitiveType(scalarType, providerManifest); } } else { edmType = (EdmType)LoadSchemaElement( type, providerManifest, convertedItemCache, newGlobalItems); // Neither FunctionImport nor its Parameters can have facets when defined in CSDL so for enums, // since they are only a CSpace concept, we need to process facets only on model functions if (isModelFunction && type is SchemaEnumType) { Debug.Assert(somFunction.Schema.DataModel == SchemaDataModelOption.EntityDataModel, "Enums live only in CSpace"); if (somParameter != null) { somParameter.ValidateAndSetTypeUsage(edmType); return somParameter.TypeUsage; } else if (somFunction != null) { var modelFunction = ((ModelFunction)somFunction); modelFunction.ValidateAndSetTypeUsage(edmType); return modelFunction.TypeUsage; } else { Debug.Fail("Should never get here."); } } } } else if (type is TypeElement) { var typeElement = type as TypeElement; edmType = typeElement.PrimitiveType; } else { var typeElement = type as ScalarType; edmType = typeElement.Type; } //Construct type usage TypeUsage usage; if (collectionKind != CollectionKind.None) { usage = convertedItemCache.GetCollectionTypeUsageWithNullFacets(edmType); } else { var entityType = edmType as EntityType; if (entityType != null && isRefType) { usage = TypeUsage.Create(new RefType(entityType)); } else { usage = convertedItemCache.GetTypeUsageWithNullFacets(edmType); } } return usage; }
private static TypeUsage GetFunctionTypeUsage( bool isModelFunction, System.Data.Entity.Core.SchemaObjectModel.Function somFunction, FacetEnabledSchemaElement somParameter, DbProviderManifest providerManifest, bool areConvertingForProviderManifest, System.Data.Entity.Core.SchemaObjectModel.SchemaType type, CollectionKind collectionKind, bool isRefType, Converter.ConversionCache convertedItemCache, Dictionary <SchemaElement, GlobalItem> newGlobalItems) { if (somParameter != null && areConvertingForProviderManifest && somParameter.HasUserDefinedFacets) { return(somParameter.TypeUsage); } if (type == null) { if (isModelFunction && somParameter != null && somParameter is Parameter) { ((Parameter)somParameter).ResolveNestedTypeNames(convertedItemCache, newGlobalItems); return(somParameter.TypeUsage); } if (somParameter == null || !(somParameter is ReturnType)) { return((TypeUsage)null); } ((ReturnType)somParameter).ResolveNestedTypeNames(convertedItemCache, newGlobalItems); return(somParameter.TypeUsage); } EdmType edmType; if (!areConvertingForProviderManifest) { ScalarType scalarType = type as ScalarType; if (scalarType != null) { if (isModelFunction && somParameter != null) { if (somParameter.TypeUsage == null) { somParameter.ValidateAndSetTypeUsage(scalarType); } return(somParameter.TypeUsage); } if (isModelFunction) { ModelFunction modelFunction = somFunction as ModelFunction; if (modelFunction.TypeUsage == null) { modelFunction.ValidateAndSetTypeUsage(scalarType); } return(modelFunction.TypeUsage); } if (somParameter != null && somParameter.HasUserDefinedFacets && somFunction.Schema.DataModel == SchemaDataModelOption.ProviderDataModel) { somParameter.ValidateAndSetTypeUsage(scalarType); return(somParameter.TypeUsage); } edmType = (EdmType)Converter.GetPrimitiveType(scalarType, providerManifest); } else { edmType = (EdmType)Converter.LoadSchemaElement(type, providerManifest, convertedItemCache, newGlobalItems); if (isModelFunction && type is SchemaEnumType) { if (somParameter != null) { somParameter.ValidateAndSetTypeUsage(edmType); return(somParameter.TypeUsage); } if (somFunction != null) { ModelFunction modelFunction = (ModelFunction)somFunction; modelFunction.ValidateAndSetTypeUsage(edmType); return(modelFunction.TypeUsage); } } } } else { edmType = !(type is TypeElement) ? (EdmType)(type as ScalarType).Type : (EdmType)(type as TypeElement).PrimitiveType; } TypeUsage typeUsage; if (collectionKind != CollectionKind.None) { typeUsage = convertedItemCache.GetCollectionTypeUsageWithNullFacets(edmType); } else { EntityType entityType = edmType as EntityType; typeUsage = entityType == null || !isRefType?convertedItemCache.GetTypeUsageWithNullFacets(edmType) : TypeUsage.Create((EdmType) new RefType(entityType)); } return(typeUsage); }
private static EdmFunction ConvertToFunction( System.Data.Entity.Core.SchemaObjectModel.Function somFunction, DbProviderManifest providerManifest, Converter.ConversionCache convertedItemCache, EntityContainer functionImportEntityContainer, Dictionary <SchemaElement, GlobalItem> newGlobalItems) { GlobalItem globalItem = (GlobalItem)null; if (!somFunction.IsFunctionImport && newGlobalItems.TryGetValue((SchemaElement)somFunction, out globalItem)) { return((EdmFunction)globalItem); } bool areConvertingForProviderManifest = somFunction.Schema.DataModel == SchemaDataModelOption.ProviderManifestModel; List <FunctionParameter> functionParameterList1 = new List <FunctionParameter>(); if (somFunction.ReturnTypeList != null) { int num = 0; foreach (ReturnType returnType in (IEnumerable <ReturnType>)somFunction.ReturnTypeList) { TypeUsage functionTypeUsage = Converter.GetFunctionTypeUsage(somFunction is ModelFunction, somFunction, (FacetEnabledSchemaElement)returnType, providerManifest, areConvertingForProviderManifest, returnType.Type, returnType.CollectionKind, returnType.IsRefType, convertedItemCache, newGlobalItems); if (functionTypeUsage == null) { return((EdmFunction)null); } string str = num == 0 ? string.Empty : num.ToString((IFormatProvider)CultureInfo.InvariantCulture); ++num; FunctionParameter functionParameter = new FunctionParameter("ReturnType" + str, functionTypeUsage, ParameterMode.ReturnValue); Converter.AddOtherContent((SchemaElement)returnType, (MetadataItem)functionParameter); functionParameterList1.Add(functionParameter); } } else if (somFunction.Type != null) { TypeUsage functionTypeUsage = Converter.GetFunctionTypeUsage(somFunction is ModelFunction, somFunction, (FacetEnabledSchemaElement)null, providerManifest, areConvertingForProviderManifest, somFunction.Type, somFunction.CollectionKind, somFunction.IsReturnAttributeReftype, convertedItemCache, newGlobalItems); if (functionTypeUsage == null) { return((EdmFunction)null); } functionParameterList1.Add(new FunctionParameter("ReturnType", functionTypeUsage, ParameterMode.ReturnValue)); } EntitySet[] entitySetArray = (EntitySet[])null; string name; if (somFunction.IsFunctionImport) { FunctionImportElement functionImportElement = (FunctionImportElement)somFunction; name = functionImportElement.Container.Name; if (functionImportElement.EntitySet != null) { EntityContainer container = functionImportEntityContainer; entitySetArray = new EntitySet[1] { Converter.GetEntitySet(functionImportElement.EntitySet, container) }; } else if (functionImportElement.ReturnTypeList != null) { EntityContainer entityContainer = functionImportEntityContainer; entitySetArray = functionImportElement.ReturnTypeList.Select <ReturnType, EntitySet>((Func <ReturnType, EntitySet>)(returnType => { if (returnType.EntitySet == null) { return((EntitySet)null); } return(Converter.GetEntitySet(returnType.EntitySet, functionImportEntityContainer)); })).ToArray <EntitySet>(); } } else { name = somFunction.Namespace; } List <FunctionParameter> functionParameterList2 = new List <FunctionParameter>(); foreach (Parameter parameter in somFunction.Parameters) { TypeUsage functionTypeUsage = Converter.GetFunctionTypeUsage(somFunction is ModelFunction, somFunction, (FacetEnabledSchemaElement)parameter, providerManifest, areConvertingForProviderManifest, parameter.Type, parameter.CollectionKind, parameter.IsRefType, convertedItemCache, newGlobalItems); if (functionTypeUsage == null) { return((EdmFunction)null); } FunctionParameter functionParameter = new FunctionParameter(parameter.Name, functionTypeUsage, Converter.GetParameterMode(parameter.ParameterDirection)); Converter.AddOtherContent((SchemaElement)parameter, (MetadataItem)functionParameter); if (parameter.Documentation != null) { functionParameter.Documentation = Converter.ConvertToDocumentation(parameter.Documentation); } functionParameterList2.Add(functionParameter); } EdmFunction edmFunction = new EdmFunction(somFunction.Name, name, Converter.GetDataSpace(providerManifest), new EdmFunctionPayload() { Schema = somFunction.DbSchema, StoreFunctionName = somFunction.StoreFunctionName, CommandText = somFunction.CommandText, EntitySets = (IList <EntitySet>)entitySetArray, IsAggregate = new bool?(somFunction.IsAggregate), IsBuiltIn = new bool?(somFunction.IsBuiltIn), IsNiladic = new bool?(somFunction.IsNiladicFunction), IsComposable = new bool?(somFunction.IsComposable), IsFromProviderManifest = new bool?(areConvertingForProviderManifest), IsFunctionImport = new bool?(somFunction.IsFunctionImport), ReturnParameters = (IList <FunctionParameter>)functionParameterList1.ToArray(), Parameters = (IList <FunctionParameter>)functionParameterList2.ToArray(), ParameterTypeSemantics = new ParameterTypeSemantics?(somFunction.ParameterTypeSemantics) }); if (!somFunction.IsFunctionImport) { newGlobalItems.Add((SchemaElement)somFunction, (GlobalItem)edmFunction); } if (somFunction.Documentation != null) { edmFunction.Documentation = Converter.ConvertToDocumentation(somFunction.Documentation); } Converter.AddOtherContent((SchemaElement)somFunction, (MetadataItem)edmFunction); return(edmFunction); }
internal override void Validate() { base.Validate(); ValidationHelper.ValidateTypeDeclaration(this, _type, _typeSubElement); ValidationHelper.ValidateFacets(this, _type, _typeUsageBuilder); if (_isRefType) { ValidationHelper.ValidateRefType(this, _type); } if (Schema.DataModel != SchemaDataModelOption.EntityDataModel) { Debug.Assert( Schema.DataModel == SchemaDataModelOption.ProviderDataModel || Schema.DataModel == SchemaDataModelOption.ProviderManifestModel, "Unexpected data model"); if (Schema.DataModel == SchemaDataModelOption.ProviderManifestModel) { // Only scalar return type is allowed for functions in provider manifest. if (_type != null && (_type is ScalarType == false || _collectionKind != CollectionKind.None) || _typeSubElement != null && _typeSubElement.Type is ScalarType == false) { var typeName = ""; if (_type != null) { typeName = Function.GetTypeNameForErrorMessage(_type, _collectionKind, _isRefType); } else if (_typeSubElement != null) { typeName = _typeSubElement.FQName; } AddError( ErrorCode.FunctionWithNonEdmTypeNotSupported, EdmSchemaErrorSeverity.Error, this, Strings.FunctionWithNonEdmPrimitiveTypeNotSupported(typeName, ParentElement.FQName)); } } else // SchemaDataModelOption.ProviderDataModel { Debug.Assert(Schema.DataModel == SchemaDataModelOption.ProviderDataModel, "Unexpected data model"); // In SSDL, function may only return a primitive type or a collection of rows. if (_type != null) { // It is not possible to define a collection of rows via a type attribute, hence any collection is not allowed. if (_type is ScalarType == false || _collectionKind != CollectionKind.None) { AddError( ErrorCode.FunctionWithNonPrimitiveTypeNotSupported, EdmSchemaErrorSeverity.Error, this, Strings.FunctionWithNonPrimitiveTypeNotSupported( _isRefType ? _unresolvedType : _type.FQName, ParentElement.FQName)); } } else if (_typeSubElement != null) { if (_typeSubElement.Type is ScalarType == false) { if (Schema.SchemaVersion < XmlConstants.StoreVersionForV3) { // Before V3 provider model functions only supported scalar return types. AddError( ErrorCode.FunctionWithNonPrimitiveTypeNotSupported, EdmSchemaErrorSeverity.Error, this, Strings.FunctionWithNonPrimitiveTypeNotSupported(_typeSubElement.FQName, ParentElement.FQName)); } else { // Starting from V3, TVFs must return collection of rows and row props can be only primitive types. // The "collection of rows" is the only option in SSDL function ReturnType subelement thus it's enforced on the XSD level, // so we can assume it here. The only thing we need to check is the type of the row properties. var collection = _typeSubElement as CollectionTypeElement; Debug.Assert(collection != null, "Can't find <CollectionType> inside TVF <ReturnType> element"); if (collection != null) { var row = collection.SubElement as RowTypeElement; Debug.Assert(row != null, "Can't find <RowType> inside TVF <ReturnType><CollectionType> element"); if (row != null) { if (row.Properties.Any(p => !p.ValidateIsScalar())) { AddError( ErrorCode.TVFReturnTypeRowHasNonScalarProperty, EdmSchemaErrorSeverity.Error, this, Strings.TVFReturnTypeRowHasNonScalarProperty); } } } } } // else type is ScalarType which is supported in all version } } } if (_typeSubElement != null) { _typeSubElement.Validate(); } }
internal ReturnType(Function parentElement) : base(parentElement) { _typeUsageBuilder = new TypeUsageBuilder(this); }