Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / EntityModel / SchemaObjectModel / Function.cs / 4 / Function.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Globalization; using System.Xml; using System.Xml.Schema; using System.Data; using System.IO; using System.Data.Metadata.Edm; using System.Data.Entity; namespace System.Data.EntityModel.SchemaObjectModel { ////// class representing the Schema element in the schema /// internal class Function : SchemaType { #region Instance Fields // if adding properties also add to InitializeObject()! private bool _isAggregate = false; private bool _isBuiltIn = false; private bool _isNiladicFunction = false; private bool _isComposable = true; private string _unresolvedEntitySet = null; private FunctionCommandText _commandText = null; private string _storeFunctionName = null; private SchemaType _type = null; private string _unresolvedType = null; // both are not specified private SchemaElementLookUpTable_parameters = null; private ReturnType _returnType = null; private CollectionKind _collectionKind = CollectionKind.None; private ParameterTypeSemantics _parameterTypeSemantics; private EntityContainer _container = null; // container is known only for function imports private EntityContainerEntitySet _entitySet = null; private string _schema; private string _functionStrongName; #endregion #region Static Fields private static System.Text.RegularExpressions.Regex s_typeParser = new System.Text.RegularExpressions.Regex(@"^(? ((Collection)|(Ref)))\s*\(\s*(? \S*)\s*\)$", System.Text.RegularExpressions.RegexOptions.Compiled); /// /// /// /// ///internal static TypeModifier RemoveTypeModifier(ref string type) { System.Text.RegularExpressions.Match match = s_typeParser.Match(type); if (match.Success) { type = match.Groups["typeName"].Value; switch (match.Groups["modifier"].Value) { case "Collection": return TypeModifier.Array; default: Debug.Assert(false, "Unexpected modifier: " + match.Groups["modifier"].Value); break; } } return TypeModifier.None; } #endregion #region Public Methods /// /// ctor for a schema function /// public Function(Schema parentElement) : base(parentElement) { } ////// ctor for a function import, which is scoped to the entity container /// /// Parent container; must not be null. protected Function(EntityContainer container) : base(container.Schema) { Debug.Assert(null != container); _container = container; // override defaults for function imports _isComposable = false; } #endregion #region Public Properties public bool IsAggregate { get { return _isAggregate; } internal set { _isAggregate = value; } } public bool IsBuiltIn { get { return _isBuiltIn; } internal set { _isBuiltIn = value; } } public bool IsNiladicFunction { get { return _isNiladicFunction; } internal set { _isNiladicFunction = value; } } public bool IsComposable { get { return _isComposable; } internal set { _isComposable = value; } } public string CommandText { get { if (_commandText != null) { return _commandText.CommandText; } return null; } } public ParameterTypeSemantics ParameterTypeSemantics { get { return _parameterTypeSemantics; } internal set { _parameterTypeSemantics = value; } } public string StoreFunctionName { get { return _storeFunctionName; } internal set { Debug.Assert(value != null, "StoreFunctionName should never be set null value"); _storeFunctionName = value; } } public SchemaType Type { get { if (null != this.ReturnType) { return this.ReturnType.Type; } else return this._type; } } public ReturnType ReturnType { get { return this._returnType; } } public SchemaElementLookUpTableParameters { get { if (_parameters == null) { _parameters = new SchemaElementLookUpTable (); } return _parameters; } } public CollectionKind CollectionKind { get { return _collectionKind; } internal set { _collectionKind = value; } } public override string Identity { get { if (String.IsNullOrEmpty(_functionStrongName)) { string name = this.FQName; System.Text.StringBuilder stringBuilder = new Text.StringBuilder(name); bool first = true; stringBuilder.Append('('); foreach (Parameter parameter in this.Parameters) { if (!first) { stringBuilder.Append(','); } else { first = false; } stringBuilder.Append(Helper.ToString(parameter.ParameterDirection)); stringBuilder.Append(' '); // we don't include the facets in the identity, since we are *not* // taking them into consideration inside the // RankFunctionParameters method of TypeResolver.cs stringBuilder.Append(parameter.Type.FQName); } stringBuilder.Append(')'); _functionStrongName = stringBuilder.ToString(); } return _functionStrongName; } } public virtual bool IsFunctionImport { get { return false; } } public EntityContainerEntitySet EntitySet { get { return _entitySet; } } public string DbSchema { get { return _schema; } } #endregion #region Protected Properties protected override bool HandleElement(XmlReader reader) { if (base.HandleElement(reader)) { return true; } else if (CanHandleElement(reader, XmlConstants.CommandText)) { HandleCommandTextFunctionElment(reader); return true; } else if (CanHandleElement(reader, XmlConstants.Parameter)) { HandleParameterElement(reader); return true; } else if (CanHandleElement(reader, XmlConstants.ReturnTypeElement)) { if (ParentElement.Schema.DataModel == SchemaDataModelOption.ProviderManifestModel) { HandleReturnTypeElement(reader); } else { SkipThroughElement(reader); } return true; } return false; } protected override bool HandleAttribute(XmlReader reader) { if (base.HandleAttribute(reader)) { return true; } else if (CanHandleAttribute(reader, XmlConstants.ReturnType)) { HandleReturnTypeAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.AggregateAttribute)) { HandleAggregateAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.BuiltInAttribute)) { HandleBuiltInAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.StoreFunctionName)) { HandleStoreFunctionNameAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.NiladicFunction)) { HandleNiladicFunctionAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.IsComposable)) { HandleIsComposableFunctionAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.ParameterTypeSemantics)) { HandleParameterTypeSemanticsAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.Schema)) { HandleDbSchemaAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.EntitySet)) { HandleEntitySetAttribute(reader); return true; } return false; } #endregion #region Internal Methods internal override void ResolveTopLevelNames() { base.ResolveTopLevelNames(); if (ReturnType != null) { Debug.Assert(Schema.DataModel == SchemaDataModelOption.ProviderManifestModel, "Only ProviderManifest will allow ReturnType elements"); ReturnType.ResolveTopLevelNames(); } Debug.Assert(this._type == null, "This must be resolved exactly once"); if (null != UnresolvedReturnType) { Debug.Assert(Schema.DataModel != SchemaDataModelOption.ProviderManifestModel, "ProviderManifest only has ReturnType as an element"); if (Schema.ResolveTypeName(this, UnresolvedReturnType, out _type)) { if (this.IsFunctionImport) { // must be either undefined, a collection of scalars, or a collection of entities if (!MeetsFunctionImportReturnTypeRequirements(_type)) { AddError(ErrorCode.FunctionImportUnsupportedReturnType, EdmSchemaErrorSeverity.Error, this, Schema.EdmVersion == XmlConstants.EdmVersionForV1 ? System.Data.Entity.Strings.FunctionImportWithUnsupportedReturnTypeV1(this.Name) : System.Data.Entity.Strings.FunctionImportWithUnsupportedReturnTypeV1_1(this.Name) ); } } else { if (!(_type is ScalarType)) { if (Schema.DataModel != SchemaDataModelOption.ProviderManifestModel) { AddError(ErrorCode.FunctionWithNonScalarTypeNotSupported, EdmSchemaErrorSeverity.Error, this, System.Data.Entity.Strings.FunctionWithNonScalarTypeNotSupported(_type.FQName, this.FQName)); } else { AddError(ErrorCode.FunctionWithNonScalarTypeNotSupported, EdmSchemaErrorSeverity.Error, this, System.Data.Entity.Strings.FunctionWithNonEdmTypeNotSupported(_type.FQName, this.FQName)); } } } } } if (IsFunctionImport) { Debug.Assert(null != _container, "function imports must know container"); // resolve entity set if (null == _entitySet && null != _unresolvedEntitySet) { _entitySet = _container.FindEntitySet(_unresolvedEntitySet); if (null == _entitySet) { AddError(ErrorCode.FunctionImportUnknownEntitySet, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.FunctionImportUnknownEntitySet(_unresolvedEntitySet, this.Name)); } } } foreach (Parameter parameter in this.Parameters) { parameter.ResolveTopLevelNames(); } } private bool MeetsFunctionImportReturnTypeRequirements(SchemaType type) { if (_type is ScalarType && _collectionKind == CollectionKind.Bag) return true; if (_type is SchemaEntityType && _collectionKind == CollectionKind.Bag) return true; if (Schema.EdmVersion == XmlConstants.EdmVersionForV1_1) { if (_type is ScalarType && _collectionKind == CollectionKind.None) return true; if (_type is SchemaEntityType && _collectionKind == CollectionKind.None) return true; if (_type is SchemaComplexType && _collectionKind == CollectionKind.None) return true; if (_type is SchemaComplexType && _collectionKind == CollectionKind.Bag) return true; } return false; } /// /// Perform local validation on function definition. /// internal override void Validate() { base.Validate(); if ( (null != _returnType && null != this._type)) { AddError(ErrorCode.AmbiguousFunctionReturnType, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.AmbiguousFunctionReturnType(this.Name, XmlConstants.ReturnType)); } if (_commandText != null) { _commandText.Validate(); } if (null == this.Type) { // only non-composable types can omit return type if (this.IsComposable) { AddError(ErrorCode.ComposableFunctionWithoutReturnType, EdmSchemaErrorSeverity.Error, Strings.ComposableFunctionMustDeclareReturnType); } } else { // non-composable functions may not declare a return type (except for function imports) if (!this.IsComposable && !this.IsFunctionImport) { AddError(ErrorCode.NonComposableFunctionWithReturnType, EdmSchemaErrorSeverity.Error, Strings.NonComposableFunctionMustNotDeclareReturnType); } } if (IsAggregate) { // Make sure that the function has exactly one parameter and that takes // a collection type if (Parameters.Count != 1) { AddError(ErrorCode.InvalidNumberOfParametersForAggregateFunction, EdmSchemaErrorSeverity.Error, this, System.Data.Entity.Strings.InvalidNumberOfParametersForAggregateFunction(FQName)); } else if (Parameters.GetElementAt(0).CollectionKind == CollectionKind.None) { // Since we have already checked that there should be exactly one parameter, it should be safe to get the // first parameter for the function Parameter param = Parameters.GetElementAt(0); AddError(ErrorCode.InvalidParameterTypeForAggregateFunction, EdmSchemaErrorSeverity.Error, this, System.Data.Entity.Strings.InvalidParameterTypeForAggregateFunction(param.Name, FQName)); } } if (!this.IsComposable) { // non-composable functions do not permit aggregate, build-in, or niladic attribute if (this.IsAggregate || this.IsNiladicFunction || this.IsBuiltIn) { AddError(ErrorCode.NonComposableFunctionAttributesNotValid, EdmSchemaErrorSeverity.Error, Strings.NonComposableFunctionHasDisallowedAttribute); } } if (null != this.CommandText) { // functions with command text are not composable if (this.IsComposable) { AddError(ErrorCode.ComposableFunctionWithCommandText, EdmSchemaErrorSeverity.Error, Strings.CommandTextFunctionsNotComposable); } // functions with command text cannot declare store function name if (null != this.StoreFunctionName) { AddError(ErrorCode.FunctionDeclaresCommandTextAndStoreFunctionName, EdmSchemaErrorSeverity.Error, Strings.CommandTextFunctionsCannotDeclareStoreFunctionName); } } if (this.IsFunctionImport) { // if entity type, verify specification of entity set and that the type is appropriate // for the entity set SchemaEntityType entityType = this.Type as SchemaEntityType; if (null != entityType) { if (null == this.EntitySet) { AddError(ErrorCode.FunctionImportReturnsEntitiesButDoesNotSpecifyEntitySet, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.FunctionImportReturnEntitiesButDoesNotSpecifyEntitySet(this.Name)); } else if (null != this.EntitySet.EntityType && !entityType.IsOfType(this.EntitySet.EntityType)) { AddError(ErrorCode.FunctionImportEntityTypeDoesNotMatchEntitySet, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.FunctionImportEntityTypeDoesNotMatchEntitySet( this.FQName, this.EntitySet.EntityType.FQName, this.EntitySet.Name, this.ParentElement.FQName)); } } if (null == entityType && null != EntitySet) { AddError(ErrorCode.FunctionImportSpecifiesEntitySetButDoesNotReturnEntityType, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.FunctionImportSpecifiesEntitySetButNotEntityType(this.Name, this.ParentElement.FQName)); } } } internal override SchemaElement Clone(SchemaElement parentElement) { Debug.Assert(IsFunctionImport, "we only support clone for FunctionImports"); Function function = new FunctionImportElement((EntityContainer)parentElement); function._isAggregate = _isAggregate; function._isBuiltIn = _isBuiltIn; function._isNiladicFunction = _isNiladicFunction; function._isComposable = _isComposable; function._entitySet = _entitySet; function._commandText = _commandText; function._storeFunctionName = _storeFunctionName; function._type = _type; function._returnType = _returnType; function._collectionKind = _collectionKind; function._parameterTypeSemantics = _parameterTypeSemantics; function._schema = _schema; function.Name = this.Name; // Clone all the parameters foreach (Parameter parameter in this.Parameters) { AddErrorKind error = function.Parameters.TryAdd((Parameter)parameter.Clone(function)); Debug.Assert(error == AddErrorKind.Succeeded, "Since we are cloning a validated function, this should never fail"); } return function; } #endregion #region Internal Properties ////// /// ///internal string UnresolvedReturnType { get { return _unresolvedType; } set { _unresolvedType = value; } } #endregion //Internal Properties #region Private Methods /// /// The method that is called when a DbSchema attribute is encountered. /// /// An XmlReader positioned at the Type attribute. private void HandleDbSchemaAttribute(XmlReader reader) { Debug.Assert(Schema.DataModel == SchemaDataModelOption.ProviderDataModel, "We shouldn't see this attribute unless we are parsing ssdl"); Debug.Assert(reader != null); _schema = reader.Value; } ////// Handler for the Version attribute /// /// xml reader currently positioned at Version attribute private void HandleAggregateAttribute(XmlReader reader) { Debug.Assert(reader != null); bool isAggregate = false; HandleBoolAttribute(reader, ref isAggregate); IsAggregate = isAggregate; } ////// Handler for the Namespace attribute /// /// xml reader currently positioned at Namespace attribute private void HandleBuiltInAttribute(XmlReader reader) { Debug.Assert(reader != null); bool isBuiltIn = false; HandleBoolAttribute(reader, ref isBuiltIn); IsBuiltIn = isBuiltIn; } ////// Handler for the Alias attribute /// /// xml reader currently positioned at Alias attribute private void HandleStoreFunctionNameAttribute(XmlReader reader) { Debug.Assert(reader != null); string value = reader.Value.ToString(); if (!String.IsNullOrEmpty(value)) { value = value.Trim(); StoreFunctionName = value; } } ////// Handler for the NiladicFunction attribute /// /// xml reader currently positioned at Namespace attribute private void HandleNiladicFunctionAttribute(XmlReader reader) { Debug.Assert(reader != null); bool isNiladicFunction = false; HandleBoolAttribute(reader, ref isNiladicFunction); IsNiladicFunction = isNiladicFunction; } ////// Handler for the IsComposable attribute /// /// xml reader currently positioned at Namespace attribute private void HandleIsComposableFunctionAttribute(XmlReader reader) { Debug.Assert(reader != null); bool isComposable = true; HandleBoolAttribute(reader, ref isComposable); IsComposable = isComposable; } private void HandleCommandTextFunctionElment(XmlReader reader) { Debug.Assert(reader != null); FunctionCommandText commandText = new FunctionCommandText(this); commandText.Parse(reader); _commandText = commandText; } private void HandleReturnTypeAttribute(XmlReader reader) { Debug.Assert(reader != null); Debug.Assert(UnresolvedReturnType == null); string type; if (!Utils.GetString(Schema, reader, out type)) return; switch (RemoveTypeModifier(ref type)) { case TypeModifier.Array: CollectionKind = CollectionKind.Bag; break; case TypeModifier.None: break; default: Debug.Assert(false, "RemoveTypeModifier already checks for this"); break; } if (!Utils.ValidateDottedName(Schema, reader, type)) return; UnresolvedReturnType = type; } ////// Handler for the Parameter Element /// /// xml reader currently positioned at Parameter Element private void HandleParameterElement(XmlReader reader) { Debug.Assert(reader != null); Parameter parameter = new Parameter(this); parameter.Parse(reader); Parameters.Add(parameter, true, Strings.ParameterNameAlreadyDefinedDuplicate); } ////// Handler for the ReturnType element /// /// xml reader currently positioned at ReturnType element private void HandleReturnTypeElement(XmlReader reader) { Debug.Assert(reader != null); ReturnType returnType = new ReturnType(this); returnType.Parse(reader); this._returnType = returnType; } ////// Handles ParameterTypeSemantics attribute /// /// private void HandleParameterTypeSemanticsAttribute(XmlReader reader) { Debug.Assert(reader != null); string value = reader.Value; if (String.IsNullOrEmpty(value)) { return; } value = value.Trim(); if (!String.IsNullOrEmpty(value)) { switch (value) { case "ExactMatchOnly": ParameterTypeSemantics = ParameterTypeSemantics.ExactMatchOnly; break; case "AllowImplicitPromotion": ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitPromotion; break; case "AllowImplicitConversion": ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion; break; default: // don't try to use the name of the function, because we are still parsing the // attributes, and we may not be to the name attribute yet. AddError(ErrorCode.InvalidValueForParameterTypeSemantics, EdmSchemaErrorSeverity.Error, reader, System.Data.Entity.Strings.InvalidValueForParameterTypeSemanticsAttribute( value)); break; } } } ////// Handler for the EntitySet attribute /// /// xml reader currently positioned at EntitySet attribute private void HandleEntitySetAttribute(XmlReader reader) { Debug.Assert(reader != null); string entitySetName; if (Utils.GetString(Schema, reader, out entitySetName)) { _unresolvedEntitySet = entitySetName; } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Globalization; using System.Xml; using System.Xml.Schema; using System.Data; using System.IO; using System.Data.Metadata.Edm; using System.Data.Entity; namespace System.Data.EntityModel.SchemaObjectModel { ////// class representing the Schema element in the schema /// internal class Function : SchemaType { #region Instance Fields // if adding properties also add to InitializeObject()! private bool _isAggregate = false; private bool _isBuiltIn = false; private bool _isNiladicFunction = false; private bool _isComposable = true; private string _unresolvedEntitySet = null; private FunctionCommandText _commandText = null; private string _storeFunctionName = null; private SchemaType _type = null; private string _unresolvedType = null; // both are not specified private SchemaElementLookUpTable_parameters = null; private ReturnType _returnType = null; private CollectionKind _collectionKind = CollectionKind.None; private ParameterTypeSemantics _parameterTypeSemantics; private EntityContainer _container = null; // container is known only for function imports private EntityContainerEntitySet _entitySet = null; private string _schema; private string _functionStrongName; #endregion #region Static Fields private static System.Text.RegularExpressions.Regex s_typeParser = new System.Text.RegularExpressions.Regex(@"^(? ((Collection)|(Ref)))\s*\(\s*(? \S*)\s*\)$", System.Text.RegularExpressions.RegexOptions.Compiled); /// /// /// /// ///internal static TypeModifier RemoveTypeModifier(ref string type) { System.Text.RegularExpressions.Match match = s_typeParser.Match(type); if (match.Success) { type = match.Groups["typeName"].Value; switch (match.Groups["modifier"].Value) { case "Collection": return TypeModifier.Array; default: Debug.Assert(false, "Unexpected modifier: " + match.Groups["modifier"].Value); break; } } return TypeModifier.None; } #endregion #region Public Methods /// /// ctor for a schema function /// public Function(Schema parentElement) : base(parentElement) { } ////// ctor for a function import, which is scoped to the entity container /// /// Parent container; must not be null. protected Function(EntityContainer container) : base(container.Schema) { Debug.Assert(null != container); _container = container; // override defaults for function imports _isComposable = false; } #endregion #region Public Properties public bool IsAggregate { get { return _isAggregate; } internal set { _isAggregate = value; } } public bool IsBuiltIn { get { return _isBuiltIn; } internal set { _isBuiltIn = value; } } public bool IsNiladicFunction { get { return _isNiladicFunction; } internal set { _isNiladicFunction = value; } } public bool IsComposable { get { return _isComposable; } internal set { _isComposable = value; } } public string CommandText { get { if (_commandText != null) { return _commandText.CommandText; } return null; } } public ParameterTypeSemantics ParameterTypeSemantics { get { return _parameterTypeSemantics; } internal set { _parameterTypeSemantics = value; } } public string StoreFunctionName { get { return _storeFunctionName; } internal set { Debug.Assert(value != null, "StoreFunctionName should never be set null value"); _storeFunctionName = value; } } public SchemaType Type { get { if (null != this.ReturnType) { return this.ReturnType.Type; } else return this._type; } } public ReturnType ReturnType { get { return this._returnType; } } public SchemaElementLookUpTableParameters { get { if (_parameters == null) { _parameters = new SchemaElementLookUpTable (); } return _parameters; } } public CollectionKind CollectionKind { get { return _collectionKind; } internal set { _collectionKind = value; } } public override string Identity { get { if (String.IsNullOrEmpty(_functionStrongName)) { string name = this.FQName; System.Text.StringBuilder stringBuilder = new Text.StringBuilder(name); bool first = true; stringBuilder.Append('('); foreach (Parameter parameter in this.Parameters) { if (!first) { stringBuilder.Append(','); } else { first = false; } stringBuilder.Append(Helper.ToString(parameter.ParameterDirection)); stringBuilder.Append(' '); // we don't include the facets in the identity, since we are *not* // taking them into consideration inside the // RankFunctionParameters method of TypeResolver.cs stringBuilder.Append(parameter.Type.FQName); } stringBuilder.Append(')'); _functionStrongName = stringBuilder.ToString(); } return _functionStrongName; } } public virtual bool IsFunctionImport { get { return false; } } public EntityContainerEntitySet EntitySet { get { return _entitySet; } } public string DbSchema { get { return _schema; } } #endregion #region Protected Properties protected override bool HandleElement(XmlReader reader) { if (base.HandleElement(reader)) { return true; } else if (CanHandleElement(reader, XmlConstants.CommandText)) { HandleCommandTextFunctionElment(reader); return true; } else if (CanHandleElement(reader, XmlConstants.Parameter)) { HandleParameterElement(reader); return true; } else if (CanHandleElement(reader, XmlConstants.ReturnTypeElement)) { if (ParentElement.Schema.DataModel == SchemaDataModelOption.ProviderManifestModel) { HandleReturnTypeElement(reader); } else { SkipThroughElement(reader); } return true; } return false; } protected override bool HandleAttribute(XmlReader reader) { if (base.HandleAttribute(reader)) { return true; } else if (CanHandleAttribute(reader, XmlConstants.ReturnType)) { HandleReturnTypeAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.AggregateAttribute)) { HandleAggregateAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.BuiltInAttribute)) { HandleBuiltInAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.StoreFunctionName)) { HandleStoreFunctionNameAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.NiladicFunction)) { HandleNiladicFunctionAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.IsComposable)) { HandleIsComposableFunctionAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.ParameterTypeSemantics)) { HandleParameterTypeSemanticsAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.Schema)) { HandleDbSchemaAttribute(reader); return true; } else if (CanHandleAttribute(reader, XmlConstants.EntitySet)) { HandleEntitySetAttribute(reader); return true; } return false; } #endregion #region Internal Methods internal override void ResolveTopLevelNames() { base.ResolveTopLevelNames(); if (ReturnType != null) { Debug.Assert(Schema.DataModel == SchemaDataModelOption.ProviderManifestModel, "Only ProviderManifest will allow ReturnType elements"); ReturnType.ResolveTopLevelNames(); } Debug.Assert(this._type == null, "This must be resolved exactly once"); if (null != UnresolvedReturnType) { Debug.Assert(Schema.DataModel != SchemaDataModelOption.ProviderManifestModel, "ProviderManifest only has ReturnType as an element"); if (Schema.ResolveTypeName(this, UnresolvedReturnType, out _type)) { if (this.IsFunctionImport) { // must be either undefined, a collection of scalars, or a collection of entities if (!MeetsFunctionImportReturnTypeRequirements(_type)) { AddError(ErrorCode.FunctionImportUnsupportedReturnType, EdmSchemaErrorSeverity.Error, this, Schema.EdmVersion == XmlConstants.EdmVersionForV1 ? System.Data.Entity.Strings.FunctionImportWithUnsupportedReturnTypeV1(this.Name) : System.Data.Entity.Strings.FunctionImportWithUnsupportedReturnTypeV1_1(this.Name) ); } } else { if (!(_type is ScalarType)) { if (Schema.DataModel != SchemaDataModelOption.ProviderManifestModel) { AddError(ErrorCode.FunctionWithNonScalarTypeNotSupported, EdmSchemaErrorSeverity.Error, this, System.Data.Entity.Strings.FunctionWithNonScalarTypeNotSupported(_type.FQName, this.FQName)); } else { AddError(ErrorCode.FunctionWithNonScalarTypeNotSupported, EdmSchemaErrorSeverity.Error, this, System.Data.Entity.Strings.FunctionWithNonEdmTypeNotSupported(_type.FQName, this.FQName)); } } } } } if (IsFunctionImport) { Debug.Assert(null != _container, "function imports must know container"); // resolve entity set if (null == _entitySet && null != _unresolvedEntitySet) { _entitySet = _container.FindEntitySet(_unresolvedEntitySet); if (null == _entitySet) { AddError(ErrorCode.FunctionImportUnknownEntitySet, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.FunctionImportUnknownEntitySet(_unresolvedEntitySet, this.Name)); } } } foreach (Parameter parameter in this.Parameters) { parameter.ResolveTopLevelNames(); } } private bool MeetsFunctionImportReturnTypeRequirements(SchemaType type) { if (_type is ScalarType && _collectionKind == CollectionKind.Bag) return true; if (_type is SchemaEntityType && _collectionKind == CollectionKind.Bag) return true; if (Schema.EdmVersion == XmlConstants.EdmVersionForV1_1) { if (_type is ScalarType && _collectionKind == CollectionKind.None) return true; if (_type is SchemaEntityType && _collectionKind == CollectionKind.None) return true; if (_type is SchemaComplexType && _collectionKind == CollectionKind.None) return true; if (_type is SchemaComplexType && _collectionKind == CollectionKind.Bag) return true; } return false; } /// /// Perform local validation on function definition. /// internal override void Validate() { base.Validate(); if ( (null != _returnType && null != this._type)) { AddError(ErrorCode.AmbiguousFunctionReturnType, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.AmbiguousFunctionReturnType(this.Name, XmlConstants.ReturnType)); } if (_commandText != null) { _commandText.Validate(); } if (null == this.Type) { // only non-composable types can omit return type if (this.IsComposable) { AddError(ErrorCode.ComposableFunctionWithoutReturnType, EdmSchemaErrorSeverity.Error, Strings.ComposableFunctionMustDeclareReturnType); } } else { // non-composable functions may not declare a return type (except for function imports) if (!this.IsComposable && !this.IsFunctionImport) { AddError(ErrorCode.NonComposableFunctionWithReturnType, EdmSchemaErrorSeverity.Error, Strings.NonComposableFunctionMustNotDeclareReturnType); } } if (IsAggregate) { // Make sure that the function has exactly one parameter and that takes // a collection type if (Parameters.Count != 1) { AddError(ErrorCode.InvalidNumberOfParametersForAggregateFunction, EdmSchemaErrorSeverity.Error, this, System.Data.Entity.Strings.InvalidNumberOfParametersForAggregateFunction(FQName)); } else if (Parameters.GetElementAt(0).CollectionKind == CollectionKind.None) { // Since we have already checked that there should be exactly one parameter, it should be safe to get the // first parameter for the function Parameter param = Parameters.GetElementAt(0); AddError(ErrorCode.InvalidParameterTypeForAggregateFunction, EdmSchemaErrorSeverity.Error, this, System.Data.Entity.Strings.InvalidParameterTypeForAggregateFunction(param.Name, FQName)); } } if (!this.IsComposable) { // non-composable functions do not permit aggregate, build-in, or niladic attribute if (this.IsAggregate || this.IsNiladicFunction || this.IsBuiltIn) { AddError(ErrorCode.NonComposableFunctionAttributesNotValid, EdmSchemaErrorSeverity.Error, Strings.NonComposableFunctionHasDisallowedAttribute); } } if (null != this.CommandText) { // functions with command text are not composable if (this.IsComposable) { AddError(ErrorCode.ComposableFunctionWithCommandText, EdmSchemaErrorSeverity.Error, Strings.CommandTextFunctionsNotComposable); } // functions with command text cannot declare store function name if (null != this.StoreFunctionName) { AddError(ErrorCode.FunctionDeclaresCommandTextAndStoreFunctionName, EdmSchemaErrorSeverity.Error, Strings.CommandTextFunctionsCannotDeclareStoreFunctionName); } } if (this.IsFunctionImport) { // if entity type, verify specification of entity set and that the type is appropriate // for the entity set SchemaEntityType entityType = this.Type as SchemaEntityType; if (null != entityType) { if (null == this.EntitySet) { AddError(ErrorCode.FunctionImportReturnsEntitiesButDoesNotSpecifyEntitySet, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.FunctionImportReturnEntitiesButDoesNotSpecifyEntitySet(this.Name)); } else if (null != this.EntitySet.EntityType && !entityType.IsOfType(this.EntitySet.EntityType)) { AddError(ErrorCode.FunctionImportEntityTypeDoesNotMatchEntitySet, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.FunctionImportEntityTypeDoesNotMatchEntitySet( this.FQName, this.EntitySet.EntityType.FQName, this.EntitySet.Name, this.ParentElement.FQName)); } } if (null == entityType && null != EntitySet) { AddError(ErrorCode.FunctionImportSpecifiesEntitySetButDoesNotReturnEntityType, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.FunctionImportSpecifiesEntitySetButNotEntityType(this.Name, this.ParentElement.FQName)); } } } internal override SchemaElement Clone(SchemaElement parentElement) { Debug.Assert(IsFunctionImport, "we only support clone for FunctionImports"); Function function = new FunctionImportElement((EntityContainer)parentElement); function._isAggregate = _isAggregate; function._isBuiltIn = _isBuiltIn; function._isNiladicFunction = _isNiladicFunction; function._isComposable = _isComposable; function._entitySet = _entitySet; function._commandText = _commandText; function._storeFunctionName = _storeFunctionName; function._type = _type; function._returnType = _returnType; function._collectionKind = _collectionKind; function._parameterTypeSemantics = _parameterTypeSemantics; function._schema = _schema; function.Name = this.Name; // Clone all the parameters foreach (Parameter parameter in this.Parameters) { AddErrorKind error = function.Parameters.TryAdd((Parameter)parameter.Clone(function)); Debug.Assert(error == AddErrorKind.Succeeded, "Since we are cloning a validated function, this should never fail"); } return function; } #endregion #region Internal Properties ////// /// ///internal string UnresolvedReturnType { get { return _unresolvedType; } set { _unresolvedType = value; } } #endregion //Internal Properties #region Private Methods /// /// The method that is called when a DbSchema attribute is encountered. /// /// An XmlReader positioned at the Type attribute. private void HandleDbSchemaAttribute(XmlReader reader) { Debug.Assert(Schema.DataModel == SchemaDataModelOption.ProviderDataModel, "We shouldn't see this attribute unless we are parsing ssdl"); Debug.Assert(reader != null); _schema = reader.Value; } ////// Handler for the Version attribute /// /// xml reader currently positioned at Version attribute private void HandleAggregateAttribute(XmlReader reader) { Debug.Assert(reader != null); bool isAggregate = false; HandleBoolAttribute(reader, ref isAggregate); IsAggregate = isAggregate; } ////// Handler for the Namespace attribute /// /// xml reader currently positioned at Namespace attribute private void HandleBuiltInAttribute(XmlReader reader) { Debug.Assert(reader != null); bool isBuiltIn = false; HandleBoolAttribute(reader, ref isBuiltIn); IsBuiltIn = isBuiltIn; } ////// Handler for the Alias attribute /// /// xml reader currently positioned at Alias attribute private void HandleStoreFunctionNameAttribute(XmlReader reader) { Debug.Assert(reader != null); string value = reader.Value.ToString(); if (!String.IsNullOrEmpty(value)) { value = value.Trim(); StoreFunctionName = value; } } ////// Handler for the NiladicFunction attribute /// /// xml reader currently positioned at Namespace attribute private void HandleNiladicFunctionAttribute(XmlReader reader) { Debug.Assert(reader != null); bool isNiladicFunction = false; HandleBoolAttribute(reader, ref isNiladicFunction); IsNiladicFunction = isNiladicFunction; } ////// Handler for the IsComposable attribute /// /// xml reader currently positioned at Namespace attribute private void HandleIsComposableFunctionAttribute(XmlReader reader) { Debug.Assert(reader != null); bool isComposable = true; HandleBoolAttribute(reader, ref isComposable); IsComposable = isComposable; } private void HandleCommandTextFunctionElment(XmlReader reader) { Debug.Assert(reader != null); FunctionCommandText commandText = new FunctionCommandText(this); commandText.Parse(reader); _commandText = commandText; } private void HandleReturnTypeAttribute(XmlReader reader) { Debug.Assert(reader != null); Debug.Assert(UnresolvedReturnType == null); string type; if (!Utils.GetString(Schema, reader, out type)) return; switch (RemoveTypeModifier(ref type)) { case TypeModifier.Array: CollectionKind = CollectionKind.Bag; break; case TypeModifier.None: break; default: Debug.Assert(false, "RemoveTypeModifier already checks for this"); break; } if (!Utils.ValidateDottedName(Schema, reader, type)) return; UnresolvedReturnType = type; } ////// Handler for the Parameter Element /// /// xml reader currently positioned at Parameter Element private void HandleParameterElement(XmlReader reader) { Debug.Assert(reader != null); Parameter parameter = new Parameter(this); parameter.Parse(reader); Parameters.Add(parameter, true, Strings.ParameterNameAlreadyDefinedDuplicate); } ////// Handler for the ReturnType element /// /// xml reader currently positioned at ReturnType element private void HandleReturnTypeElement(XmlReader reader) { Debug.Assert(reader != null); ReturnType returnType = new ReturnType(this); returnType.Parse(reader); this._returnType = returnType; } ////// Handles ParameterTypeSemantics attribute /// /// private void HandleParameterTypeSemanticsAttribute(XmlReader reader) { Debug.Assert(reader != null); string value = reader.Value; if (String.IsNullOrEmpty(value)) { return; } value = value.Trim(); if (!String.IsNullOrEmpty(value)) { switch (value) { case "ExactMatchOnly": ParameterTypeSemantics = ParameterTypeSemantics.ExactMatchOnly; break; case "AllowImplicitPromotion": ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitPromotion; break; case "AllowImplicitConversion": ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion; break; default: // don't try to use the name of the function, because we are still parsing the // attributes, and we may not be to the name attribute yet. AddError(ErrorCode.InvalidValueForParameterTypeSemantics, EdmSchemaErrorSeverity.Error, reader, System.Data.Entity.Strings.InvalidValueForParameterTypeSemanticsAttribute( value)); break; } } } ////// Handler for the EntitySet attribute /// /// xml reader currently positioned at EntitySet attribute private void HandleEntitySetAttribute(XmlReader reader) { Debug.Assert(reader != null); string entitySetName; if (Utils.GetString(Schema, reader, out entitySetName)) { _unresolvedEntitySet = entitySetName; } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DecimalConverter.cs
- AsyncResult.cs
- DataServiceClientException.cs
- IndexedWhereQueryOperator.cs
- DataContractSerializerSection.cs
- CacheAxisQuery.cs
- ConnectionOrientedTransportElement.cs
- Gdiplus.cs
- XmlDocumentFragment.cs
- QuaternionRotation3D.cs
- TypeDescriptor.cs
- CaretElement.cs
- SqlCommand.cs
- HtmlHead.cs
- ClonableStack.cs
- XamlVector3DCollectionSerializer.cs
- DBConnectionString.cs
- SubMenuStyleCollection.cs
- OleDbCommand.cs
- DesignerCatalogPartChrome.cs
- DescendentsWalker.cs
- BroadcastEventHelper.cs
- Interlocked.cs
- SaveRecipientRequest.cs
- MessageDirection.cs
- ToolStripGripRenderEventArgs.cs
- HttpAsyncResult.cs
- ReaderWriterLockWrapper.cs
- EditableTreeList.cs
- COSERVERINFO.cs
- SecUtil.cs
- UnknownWrapper.cs
- SecurityTokenRequirement.cs
- MultipleViewProviderWrapper.cs
- ProviderConnectionPoint.cs
- FontUnitConverter.cs
- DataGridViewHitTestInfo.cs
- mediaeventshelper.cs
- Decoder.cs
- SqlBooleanMismatchVisitor.cs
- StateDesigner.cs
- NavigationWindow.cs
- NodeCounter.cs
- InvalidateEvent.cs
- SqlReorderer.cs
- ComplexObject.cs
- HtmlInputButton.cs
- FolderLevelBuildProviderCollection.cs
- ChannelPool.cs
- ImageMapEventArgs.cs
- PackUriHelper.cs
- DbXmlEnabledProviderManifest.cs
- LinkedList.cs
- PreviewControlDesigner.cs
- EnumBuilder.cs
- DiagnosticTraceSchemas.cs
- TemplateModeChangedEventArgs.cs
- CellIdBoolean.cs
- Formatter.cs
- DocumentNUp.cs
- DesignerSerializerAttribute.cs
- Errors.cs
- EffectiveValueEntry.cs
- SQLResource.cs
- StreamResourceInfo.cs
- FaultConverter.cs
- ComboBox.cs
- SerializationInfo.cs
- TextEndOfParagraph.cs
- CapabilitiesRule.cs
- TableLayoutPanel.cs
- DataGridViewRowConverter.cs
- ResourceDictionary.cs
- UTF8Encoding.cs
- RepeatButton.cs
- AsymmetricSignatureFormatter.cs
- CqlParser.cs
- Constant.cs
- ColumnHeader.cs
- ClientRoleProvider.cs
- DSACryptoServiceProvider.cs
- StrokeCollectionDefaultValueFactory.cs
- StructuralCache.cs
- columnmapkeybuilder.cs
- ReflectionUtil.cs
- CompiledQuery.cs
- CodeBlockBuilder.cs
- ExtensionWindowHeader.cs
- MarkupWriter.cs
- DomainUpDown.cs
- ObjectDataSource.cs
- DataRecordInfo.cs
- MimeFormatExtensions.cs
- HashHelper.cs
- RowSpanVector.cs
- DbConnectionPoolCounters.cs
- DesignerPerfEventProvider.cs
- EventArgs.cs
- ApplicationSettingsBase.cs
- RelationshipConstraintValidator.cs