/// <summary> /// Computes the closure of common super types of the set of predefined edm primitive types /// This is done only once and cached as opposed to previous implementation that was computing /// this for every new pair of types. /// </summary> private static void ComputeCommonTypeClosure() { if (null != _commonTypeClosure) { return; } objectModel.ReadOnlyCollection <PrimitiveType>[,] commonTypeClosure = new objectModel.ReadOnlyCollection <PrimitiveType> [EdmConstants.NumPrimitiveTypes, EdmConstants.NumPrimitiveTypes]; for (int i = 0; i < EdmConstants.NumPrimitiveTypes; i++) { commonTypeClosure[i, i] = Helper.EmptyPrimitiveTypeReadOnlyCollection; } objectModel.ReadOnlyCollection <PrimitiveType> primitiveTypes = EdmProviderManifest.Instance.GetStoreTypes(); for (int i = 0; i < EdmConstants.NumPrimitiveTypes; i++) { for (int j = 0; j < i; j++) { commonTypeClosure[i, j] = Intersect(EdmProviderManifest.Instance.GetPromotionTypes(primitiveTypes[i]), EdmProviderManifest.Instance.GetPromotionTypes(primitiveTypes[j])); commonTypeClosure[j, i] = commonTypeClosure[i, j]; } } TypeSemantics.AssertTypeInvariant("Common Type closure is incorrect", delegate() { for (int i = 0; i < EdmConstants.NumPrimitiveTypes; i++) { for (int j = 0; j < EdmConstants.NumPrimitiveTypes; j++) { if (commonTypeClosure[i, j] != commonTypeClosure[j, i]) { return(false); } if (i == j && commonTypeClosure[i, j].Count != 0) { return(false); } } } return(true); }); System.Threading.Interlocked.CompareExchange <objectModel.ReadOnlyCollection <PrimitiveType> [, ]>(ref _commonTypeClosure, commonTypeClosure, null); }
/// <summary> /// Validates whether cspace and sspace types are compatible. /// </summary> /// <param name="cspaceType">Type in C-Space. Must be a primitive or enumeration type.</param> /// <param name="storeType">C-Space equivalent of S-space Type. Must be a primitive type.</param> /// <returns> /// <c>true</c> if the types are compatible. <c>false</c> otherwise. /// </returns> /// <remarks> /// This methods validate whether cspace and sspace types are compatible. The types are /// compatible if: /// both are primitive and the cspace type is a subtype of sspace type /// or /// cspace type is an enumeration type whose underlying type is a subtype of sspace type. /// </remarks> private static bool ValidateScalarTypesAreCompatible(TypeUsage cspaceType, TypeUsage storeType) { Debug.Assert(cspaceType != null, "cspaceType != null"); Debug.Assert(storeType != null, "storeType != null"); Debug.Assert(cspaceType.EdmType.DataSpace == DataSpace.CSpace, "cspace property must have a cspace type"); Debug.Assert(storeType.EdmType.DataSpace == DataSpace.CSpace, "storeType type usage must have a sspace type"); Debug.Assert( Helper.IsScalarType(cspaceType.EdmType), "cspace property must be of a primitive or enumeration type"); Debug.Assert(Helper.IsPrimitiveType(storeType.EdmType), "storeType property must be a primitive type"); if (Helper.IsEnumType(cspaceType.EdmType)) { // For enum cspace type check whether its underlying type is a subtype of the store type. Note that // TypeSemantics.IsSubTypeOf uses only TypeUsage.EdmType for primitive types so there is no need to copy facets // from the enum type property to the underlying type TypeUsage created here since they wouldn't be used anyways. return(TypeSemantics.IsSubTypeOf(TypeUsage.Create(Helper.GetUnderlyingEdmTypeForEnumType(cspaceType.EdmType)), storeType)); } return(TypeSemantics.IsSubTypeOf(cspaceType, storeType)); }
/// <summary> /// Returns a Model type usage for a provider type /// </summary> /// <returns>model (CSpace) type usage</returns> internal TypeUsage GetModelTypeUsage() { if (_modelTypeUsage == null) { EdmType edmType = this.EdmType; // If the edm type is already a cspace type, return the same type if (edmType.DataSpace == DataSpace.CSpace || edmType.DataSpace == DataSpace.OSpace) { return(this); } TypeUsage result; if (Helper.IsRowType(edmType)) { RowType sspaceRowType = (RowType)edmType; EdmProperty[] properties = new EdmProperty[sspaceRowType.Properties.Count]; for (int i = 0; i < properties.Length; i++) { EdmProperty sspaceProperty = sspaceRowType.Properties[i]; TypeUsage newTypeUsage = sspaceProperty.TypeUsage.GetModelTypeUsage(); properties[i] = new EdmProperty(sspaceProperty.Name, newTypeUsage); } RowType edmRowType = new RowType(properties, sspaceRowType.InitializerMetadata); result = TypeUsage.Create(edmRowType, this.Facets); } else if (Helper.IsCollectionType(edmType)) { CollectionType sspaceCollectionType = ((CollectionType)edmType); TypeUsage newTypeUsage = sspaceCollectionType.TypeUsage.GetModelTypeUsage(); result = TypeUsage.Create(new CollectionType(newTypeUsage), this.Facets); } else if (Helper.IsRefType(edmType)) { System.Diagnostics.Debug.Assert(((RefType)edmType).ElementType.DataSpace == DataSpace.CSpace); result = this; } else if (Helper.IsPrimitiveType(edmType)) { result = ((PrimitiveType)edmType).ProviderManifest.GetEdmType(this); if (result == null) { throw EntityUtil.ProviderIncompatible(System.Data.Entity.Strings.Mapping_ProviderReturnsNullType(this.ToString())); } if (!TypeSemantics.IsNullable(this)) { result = TypeUsage.Create(result.EdmType, OverrideFacetValues(result.Facets, new FacetValues { Nullable = false })); } } else if (Helper.IsEntityTypeBase(edmType) || Helper.IsComplexType(edmType)) { result = this; } else { System.Diagnostics.Debug.Assert(false, "Unexpected type found in entity data reader"); return(null); } System.Threading.Interlocked.CompareExchange(ref _modelTypeUsage, result, null); } return(_modelTypeUsage); }
/// <summary> /// determines if type is of Boolean Kind /// </summary> /// <param name="type"></param> /// <returns></returns> internal static bool IsBooleanType(TypeUsage type) { return(TypeSemantics.IsPrimitiveType(type, PrimitiveTypeKind.Boolean)); }