Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Metadata / TypeSemantics.cs / 1305376 / TypeSemantics.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Diagnostics; using objectModel = System.Collections.ObjectModel; namespace System.Data.Metadata.Edm { ////// Provides type semantics service, type operations and type predicates for the EDM type system. /// ////// For detailed functional specification, see "The EDP Type System.docx" and "edm.spec.doc". /// Notes: /// 1) The notion of 'type' for the sake of type operation semantics is based on TypeUsage, i.e., EdmType *plus* facets. /// /// 2) EDM built-in primitive types are defined by the EDM Provider Manifest. /// /// 3) SubType and Promotable are similar notions however subtyping is stricter than promotability. Subtyping is used for mapping /// validation while Promotability is used in query, update expression static type validation. /// internal static class TypeSemantics { #region Fields // // cache commom super type closure // static private objectModel.ReadOnlyCollection[,] _commonTypeClosure; #endregion // // 'Public' Interface // #region 'Public' Interface /// /// Determines whether two types are exactly equal. /// For row types, this INCLUDES field names as well as types. /// For primitive types this requires exactly the same set of facets with the same values on each type. /// /// The first type to compare. /// The second type to compare. ///If the two types are structurally equal, internal static bool IsEqual(TypeUsage type1, TypeUsage type2) { return CompareTypes(type1, type2, false /*equivalenceOnly*/); } ///true ; otherwisefalse ./// Determines if the two types are structurally equivalent. /// /// /// ////// Equivalence for nomimal types is based on lexical identity and structural equivalence for structural types. /// Structural equivalence for row types is based only on equivalence of field types, field names are ignored. /// ///true if equivalent, false otherwise internal static bool IsStructurallyEqual(TypeUsage fromType, TypeUsage toType) { return CompareTypes(fromType, toType, true /*equivalenceOnly*/); } ////// determines if two types are equivalent or if fromType is promotable to toType /// /// /// ///true if fromType equivalent or promotable to toType, false otherwise internal static bool IsStructurallyEqualOrPromotableTo(TypeUsage fromType, TypeUsage toType) { return IsStructurallyEqual(fromType, toType) || IsPromotableTo(fromType, toType); } ////// determines if subType is equal to or a sub-type of superType. /// /// /// ///true if subType is equal to or a sub-type of superType, false otherwise internal static bool IsSubTypeOf(TypeUsage subType, TypeUsage superType) { Debug.Assert(subType != null, "subType must not be NULL"); Debug.Assert(superType != null, "superType must not be NULL"); if (subType.EdmEquals(superType)) { return true; } if (Helper.IsPrimitiveType(subType.EdmType) && Helper.IsPrimitiveType(superType.EdmType)) { return IsPrimitiveTypeSubTypeOf(subType, superType); } return subType.IsSubtypeOf(superType); } ////// determines if subType EdmType is a sub-type of superType EdmType. /// /// /// ///true if subType is a sub-type of superType, false otherwise internal static bool IsSubTypeOf(EdmType subEdmType, EdmType superEdmType) { return subEdmType.IsSubtypeOf(superEdmType); } ////// Determines if fromType is promotable to toType. /// /// /// ///true if fromType is promotable to toType, false otherwise internal static bool IsPromotableTo(TypeUsage fromType, TypeUsage toType) { Debug.Assert(fromType != null, "fromType must not be NULL"); Debug.Assert(toType != null, "toType must not be NULL"); if (toType.EdmEquals(fromType)) { return true; } if (IsNullType(fromType) && !Helper.IsCollectionType(toType.EdmType)) { // we can implicitly promote null to any type except collection return true; } if (Helper.IsPrimitiveType(fromType.EdmType) && Helper.IsPrimitiveType(toType.EdmType)) { return IsPrimitiveTypePromotableTo(fromType, toType); } else if (Helper.IsCollectionType(fromType.EdmType) && Helper.IsCollectionType(toType.EdmType)) { return IsPromotableTo(TypeHelpers.GetElementTypeUsage(fromType), TypeHelpers.GetElementTypeUsage(toType)); } else if (Helper.IsEntityTypeBase(fromType.EdmType) && Helper.IsEntityTypeBase(toType.EdmType)) { return fromType.EdmType.IsSubtypeOf(toType.EdmType); } else if (Helper.IsRefType(fromType.EdmType) && Helper.IsRefType(toType.EdmType)) { return IsPromotableTo(TypeHelpers.GetElementTypeUsage(fromType), TypeHelpers.GetElementTypeUsage(toType)); } else if (Helper.IsRowType(fromType.EdmType) && Helper.IsRowType(toType.EdmType)) { return IsPromotableTo((RowType)fromType.EdmType, (RowType)toType.EdmType); } else if (Helper.IsComplexType(fromType.EdmType) && Helper.IsComplexType(toType.EdmType)) { // complex types are not polymorphic in v1 return fromType.EdmType.EdmEquals(toType.EdmType); } return false; } ////// Flattens composite type down to primitive, entity/relship, complex and null type leafs. /// internal static IEnumerableFlattenType(TypeUsage type) { Func isLeaf = t => !(Helper.IsCollectionType(t.EdmType) || Helper.IsRefType(t.EdmType) || Helper.IsRowType(t.EdmType)); Func > getImmediateSubNodes = t => { if (Helper.IsCollectionType(t.EdmType) || Helper.IsRefType(t.EdmType)) { return new[] { TypeHelpers.GetElementTypeUsage(t) }; } else if (Helper.IsRowType(t.EdmType)) { return ((RowType)t.EdmType).Properties.Select(p => p.TypeUsage); } else { Debug.Fail("cannot enumerate subnodes of a leaf node"); return new TypeUsage[] { }; } }; return Common.Utils.Helpers.GetLeafNodes (type, isLeaf, getImmediateSubNodes); } /// /// determines if fromType can be casted to toType. /// /// /// ///cast operation is allowed on primitive types only ///internal static bool IsCastAllowed(TypeUsage fromType, TypeUsage toType) { return (IsNullType(fromType) || Helper.IsPrimitiveType(fromType.EdmType)) && Helper.IsPrimitiveType(toType.EdmType); } /// /// Determines if a common super type (LUB) exists between type1 and type2. /// /// /// /// ////// true if a common super type between type1 and type2 exists and out commonType represents the common super type. /// false otherwise along with commonType as null /// internal static bool TryGetCommonType(TypeUsage type1, TypeUsage type2, out TypeUsage commonType) { Debug.Assert(type1 != null, "type1 must not be NULL"); Debug.Assert(type2 != null, "type2 must not be NULL"); commonType = null; if (type1.EdmEquals(type2) || IsNullType(type1)) { commonType = ForgetConstraints(type2); return true; } if (IsNullType(type2)) { commonType = ForgetConstraints(type1); return true; } if (Helper.IsPrimitiveType(type1.EdmType) && Helper.IsPrimitiveType(type2.EdmType)) { return TryGetCommonPrimitiveType(type1, type2, out commonType); } EdmType commonEdmType; if (TryGetCommonType(type1.EdmType, type2.EdmType, out commonEdmType)) { commonType = ForgetConstraints(TypeUsage.Create(commonEdmType)); return true; } commonType = null; return false; } ////// Gets a Common super-type of type1 and type2 if one exists. null otherwise. /// /// /// ///internal static TypeUsage GetCommonType(TypeUsage type1, TypeUsage type2) { TypeUsage commonType = null; if (TypeSemantics.TryGetCommonType(type1, type2, out commonType)) { return commonType; } return null; } /// /// Asserts that a given type is an entity and is one of the relationship 'ends' /// /// /// ///internal static bool IsTypeValidForRelationship(TypeUsage type, RelationshipType relationshipType) { Debug.Assert(type != null, "type must not be null"); Debug.Assert(relationshipType != null, "relationshipType must not be null"); if (Helper.IsEntityType(type.EdmType)) { foreach (EdmMember member in relationshipType.Members) { if (TypeSemantics.IsValidPolymorphicCast(type.EdmType, TypeHelpers.GetElementTypeUsage(member.TypeUsage).EdmType)) { return true; } } } return false; } /// /// determines if an EdmFunction is an aggregate function /// /// ///internal static bool IsAggregateFunction(EdmFunction function) { return function.AggregateAttribute; } /// /// determines if fromType can be cast to toType. this operation is valid only /// if fromtype and totype are polimorphic types. /// /// /// ///internal static bool IsValidPolymorphicCast(TypeUsage fromType, TypeUsage toType) { if (!IsPolymorphicType(fromType) || !IsPolymorphicType(toType)) { return false; } return (IsStructurallyEqual(fromType, toType) || IsSubTypeOf(fromType, toType) || IsSubTypeOf(toType, fromType)); } /// /// determines if fromEdmType can be cast to toEdmType. this operation is valid only /// if fromtype and totype are polimorphic types. /// /// /// ///internal static bool IsValidPolymorphicCast(EdmType fromEdmType, EdmType toEdmType) { return IsValidPolymorphicCast(TypeUsage.Create(fromEdmType), TypeUsage.Create(toEdmType)); } /// /// determines if type is a nominal type, i.e., EntityType or ComplexType /// /// ///static internal bool IsNominalType(TypeUsage type) { return IsEntityType(type) || IsComplexType(type); } /// /// determines if type is a collection type. /// /// ///internal static bool IsCollectionType(TypeUsage type) { return Helper.IsCollectionType(type.EdmType); } /// /// determines if type is a complex type. /// /// ///internal static bool IsComplexType(TypeUsage type) { return (BuiltInTypeKind.ComplexType == type.EdmType.BuiltInTypeKind); } /// /// determines if type is an EntityType /// /// ///internal static bool IsEntityType(TypeUsage type) { return Helper.IsEntityType(type.EdmType); } /// /// determines if type is a Relationship Type. /// /// ///internal static bool IsRelationshipType(TypeUsage type) { return (BuiltInTypeKind.AssociationType == type.EdmType.BuiltInTypeKind); } /// /// determines if type is of EnumerationType. /// /// ///internal static bool IsEnumerationType(TypeUsage type) { return (BuiltInTypeKind.EnumType == type.EdmType.BuiltInTypeKind); } /// /// determines if edmType is null or NullType /// /// ///[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static bool IsNullOrNullType(EdmType edmType) { return (null == edmType) || edmType.Equals(TypeUsage.NullType.EdmType); } /// /// determines if type is null or NullType /// /// ///internal static bool IsNullOrNullType(TypeUsage type) { return (null == type) || TypeSemantics.IsNullType(type); } /// /// determines if type is NullType /// /// ///internal static bool IsNullType(TypeUsage type) { Debug.Assert(type != null, "type cannot be null"); return type.EdmEquals(MetadataItem.NullType); } /// /// Determines if type is a numeric type, i.e., is one of: /// Byte, Int16, Int32, Int64, Decimal, Single or Double /// /// ///internal static bool IsNumericType(TypeUsage type) { return (IsIntegerNumericType(type) || IsFixedPointNumericType(type) || IsFloatPointNumericType(type)); } /// /// Determines if type is an integer numeric type, i.e., is one of: Byte, Int16, Int32, Int64 /// /// ///internal static bool IsIntegerNumericType(TypeUsage type) { PrimitiveTypeKind typeKind; if (TypeHelpers.TryGetPrimitiveTypeKind(type, out typeKind)) { switch (typeKind) { case PrimitiveTypeKind.Byte: case PrimitiveTypeKind.Int16: case PrimitiveTypeKind.Int32: case PrimitiveTypeKind.Int64: case PrimitiveTypeKind.SByte: return true; default: return false; } } return false; } /// /// Determines if type is an fixed point numeric type, i.e., is one of: Decimal /// /// ///internal static bool IsFixedPointNumericType(TypeUsage type) { PrimitiveTypeKind typeKind; if (TypeHelpers.TryGetPrimitiveTypeKind(type, out typeKind)) { return (typeKind == PrimitiveTypeKind.Decimal); } return false; } /// /// Determines if type is an float point numeric type, i.e., is one of: Single or Double. /// /// ///internal static bool IsFloatPointNumericType(TypeUsage type) { PrimitiveTypeKind typeKind; if (TypeHelpers.TryGetPrimitiveTypeKind(type, out typeKind)) { return (typeKind == PrimitiveTypeKind.Double || typeKind == PrimitiveTypeKind.Single); } return false; } /// /// Determines if type is an unsigned integer numeric type, i.e., is Byte /// /// ///internal static bool IsUnsignedNumericType(TypeUsage type) { PrimitiveTypeKind typeKind; if (TypeHelpers.TryGetPrimitiveTypeKind(type, out typeKind)) { switch (typeKind) { case PrimitiveTypeKind.Byte: return true; default: return false; } } return false; } /// /// determines if type is a polimorphic type, ie, EntityType or ComplexType. /// /// ///internal static bool IsPolymorphicType(TypeUsage type) { return (IsEntityType(type) || IsComplexType(type)); } /// /// determines if type is of Boolean Kind /// /// ///internal static bool IsBooleanType(TypeUsage type) { return TypeSemantics.IsPrimitiveType(type, PrimitiveTypeKind.Boolean); } /// /// determines if type is a primitive/scalar type. /// /// ///internal static bool IsPrimitiveType(TypeUsage type) { return Helper.IsPrimitiveType(type.EdmType); } /// /// determines if type is a primitive type of given primitiveTypeKind /// /// /// ///internal static bool IsPrimitiveType(TypeUsage type, PrimitiveTypeKind primitiveTypeKind) { PrimitiveTypeKind typeKind; if (TypeHelpers.TryGetPrimitiveTypeKind(type, out typeKind)) { return (typeKind == primitiveTypeKind); } return false; } /// /// determines if type is a RowType /// /// ///internal static bool IsRowType(TypeUsage type) { return Helper.IsRowType(type.EdmType); } /// /// determines if type is a ReferenceType /// /// ///internal static bool IsReferenceType(TypeUsage type) { return Helper.IsRefType(type.EdmType); } /// /// determines if type is a structural type, ie, EntityType, ComplexType, RowType or ReferenceType. /// /// ///internal static bool IsStructuralType(TypeUsage type) { return Helper.IsStructuralType(type.EdmType); } /// /// determines if edmMember is part of the key of it's defining type. /// /// ///internal static bool IsPartOfKey(EdmMember edmMember) { if (Helper.IsRelationshipEndMember(edmMember)) { return ((RelationshipType)edmMember.DeclaringType).KeyMembers.Contains(edmMember); } if (!Helper.IsEdmProperty(edmMember)) { return false; } if (Helper.IsEntityTypeBase(edmMember.DeclaringType)) { return ((EntityTypeBase)edmMember.DeclaringType).KeyMembers.Contains(edmMember); } return false; } /// /// determines if type is Nullable. /// /// ///internal static bool IsNullable(TypeUsage type) { Facet nullableFacet; if (type.Facets.TryGetValue(EdmProviderManifest.NullableFacetName, false, out nullableFacet)) { return (bool)nullableFacet.Value; } return true; } /// /// determines if edmMember is Nullable. /// /// ///internal static bool IsNullable(EdmMember edmMember) { return IsNullable(edmMember.TypeUsage); } /// /// determines if given type is equal-comparable. /// /// ///true if equal-comparable, false otherwise internal static bool IsEqualComparable(TypeUsage type) { return IsEqualComparable(type.EdmType); } ////// Determines if type1 is equal-comparable to type2. /// in order for type1 and type2 to be equal-comparable, they must be /// individualy equal-comparable and have a common super-type. /// /// an instance of a TypeUsage /// an instance of a TypeUsage ///internal static bool IsEqualComparableTo(TypeUsage type1, TypeUsage type2) { if (IsEqualComparable(type1) && IsEqualComparable(type2)) { return HasCommonType(type1, type2); } return false; } /// true if type1 and type2 are equal-comparable,false otherwise/// Determines if given type is order-comparable /// /// ///internal static bool IsOrderComparable(TypeUsage type) { Debug.Assert(null != type, "type must not be null"); return IsOrderComparable(type.EdmType); } /// Determines if type1 is order-comparable to type2. /// in order for type1 and type2 to be order-comparable, they must be /// individualy order-comparable and have a common super-type. /// /// an instance of a TypeUsage /// an instance of a TypeUsage /// internal static bool IsOrderComparableTo(TypeUsage type1, TypeUsage type2) { if (IsOrderComparable(type1) && IsOrderComparable(type2)) { return HasCommonType(type1, type2); } return false; } /// true if type1 and type2 are order-comparable,false otherwise/// Removes facets that are not type constraints. /// /// ///internal static TypeUsage ForgetConstraints(TypeUsage type) { if (Helper.IsPrimitiveType(type.EdmType)) { return EdmProviderManifest.Instance.ForgetScalarConstraints(type); } return type; } [System.Diagnostics.Conditional("DEBUG")] static internal void AssertTypeInvariant(string message, Func assertPredicate) { System.Diagnostics.Debug.Assert(assertPredicate(), "Type invariant check FAILED\n" + message); } #endregion // Internal interface // // Private Interface // #region Private Interface #region Subtyping private static bool IsPrimitiveTypeSubTypeOf(TypeUsage fromType, TypeUsage toType) { Debug.Assert(fromType != null, "fromType must not be null"); Debug.Assert(Helper.IsPrimitiveType(fromType.EdmType), "fromType must be primitive type"); Debug.Assert(toType != null, "toType must not be null"); Debug.Assert(Helper.IsPrimitiveType(toType.EdmType), "toType must be primitive type"); if (!IsSubTypeOf((PrimitiveType)fromType.EdmType, (PrimitiveType)toType.EdmType)) { return false; } return true; } private static bool IsSubTypeOf(PrimitiveType subPrimitiveType, PrimitiveType superPrimitiveType) { if (object.ReferenceEquals(subPrimitiveType, superPrimitiveType)) { return true; } objectModel.ReadOnlyCollection superTypes = EdmProviderManifest.Instance.GetPromotionTypes(subPrimitiveType); return (-1 != superTypes.IndexOf(superPrimitiveType)); } #endregion // Subtyping #region Promotability private static bool IsPromotableTo(RowType fromRowType, RowType toRowType) { Debug.Assert(fromRowType != null && toRowType != null); if (fromRowType.Properties.Count != toRowType.Properties.Count) { return false; } for (int i = 0; i < fromRowType.Properties.Count; i++) { if (!IsPromotableTo(fromRowType.Properties[i].TypeUsage, toRowType.Properties[i].TypeUsage)) { return false; } } return true; } private static bool IsPrimitiveTypePromotableTo(TypeUsage fromType, TypeUsage toType) { Debug.Assert(fromType != null, "fromType must not be null"); Debug.Assert(Helper.IsPrimitiveType(fromType.EdmType), "fromType must be primitive type"); Debug.Assert(toType != null, "toType must not be null"); Debug.Assert(Helper.IsPrimitiveType(toType.EdmType), "toType must be primitive type"); if (!IsSubTypeOf((PrimitiveType)fromType.EdmType, (PrimitiveType)toType.EdmType)) { return false; } return true; } #endregion // promotability #region Common Super-Type private static bool TryGetCommonType(EdmType edmType1, EdmType edmType2, out EdmType commonEdmType) { Debug.Assert(edmType1 != null && edmType2 != null); if (edmType2 == edmType1) { commonEdmType = edmType1; return true; } if (Helper.IsPrimitiveType(edmType1) && Helper.IsPrimitiveType(edmType2)) { return TryGetCommonType((PrimitiveType)edmType1, (PrimitiveType)edmType2, out commonEdmType); } else if (Helper.IsCollectionType(edmType1) && Helper.IsCollectionType(edmType2)) { return TryGetCommonType((CollectionType)edmType1, (CollectionType)edmType2, out commonEdmType); } else if (Helper.IsEntityTypeBase(edmType1) && Helper.IsEntityTypeBase(edmType2)) { return TryGetCommonBaseType(edmType1, edmType2, out commonEdmType); } else if (Helper.IsRefType(edmType1) && Helper.IsRefType(edmType2)) { return TryGetCommonType((RefType)edmType1, (RefType)edmType2, out commonEdmType); } else if (Helper.IsRowType(edmType1) && Helper.IsRowType(edmType2)) { return TryGetCommonType((RowType)edmType1, (RowType)edmType2, out commonEdmType); } else { commonEdmType = null; return false; } } private static bool TryGetCommonPrimitiveType(TypeUsage type1, TypeUsage type2, out TypeUsage commonType) { Debug.Assert(type1 != null, "type1 must not be null"); Debug.Assert(Helper.IsPrimitiveType(type1.EdmType), "type1 must be primitive type"); Debug.Assert(type2 != null, "type2 must not be null"); Debug.Assert(Helper.IsPrimitiveType(type2.EdmType), "type2 must be primitive type"); commonType = null; if (IsPromotableTo(type1, type2)) { commonType = ForgetConstraints(type2); return true; } if (IsPromotableTo(type2, type1)) { commonType = ForgetConstraints(type1); return true; } objectModel.ReadOnlyCollection superTypes = GetPrimitiveCommonSuperTypes((PrimitiveType)type1.EdmType, (PrimitiveType)type2.EdmType); if (superTypes.Count == 0) { return false; } commonType = TypeUsage.CreateDefaultTypeUsage(superTypes[0]); return null != commonType; } private static bool TryGetCommonType(PrimitiveType primitiveType1, PrimitiveType primitiveType2, out EdmType commonType) { commonType = null; if (IsSubTypeOf(primitiveType1, primitiveType2)) { commonType = primitiveType2; return true; } if (IsSubTypeOf(primitiveType2, primitiveType1)) { commonType = primitiveType1; return true; } objectModel.ReadOnlyCollection superTypes = GetPrimitiveCommonSuperTypes(primitiveType1, primitiveType2); if (superTypes.Count > 0) { commonType = superTypes[0]; return true; } return false; } private static bool TryGetCommonType(CollectionType collectionType1, CollectionType collectionType2, out EdmType commonType) { TypeUsage commonTypeUsage = null; if (!TryGetCommonType(collectionType1.TypeUsage, collectionType2.TypeUsage, out commonTypeUsage)) { commonType = null; return false; } commonType = new CollectionType(commonTypeUsage); return true; } private static bool TryGetCommonType(RefType refType1, RefType reftype2, out EdmType commonType) { Debug.Assert(refType1.ElementType != null && reftype2.ElementType != null); if (!TryGetCommonType(refType1.ElementType, reftype2.ElementType, out commonType)) { return false; } commonType = new RefType((EntityType)commonType); return true; } private static bool TryGetCommonType(RowType rowType1, RowType rowType2, out EdmType commonRowType) { if (rowType1.Properties.Count != rowType2.Properties.Count || rowType1.InitializerMetadata != rowType2.InitializerMetadata) { commonRowType = null; return false; } // find a common type for every property List commonProperties = new List (); for (int i = 0; i < rowType1.Properties.Count; i++) { TypeUsage columnCommonTypeUsage; if (!TryGetCommonType(rowType1.Properties[i].TypeUsage, rowType2.Properties[i].TypeUsage, out columnCommonTypeUsage)) { commonRowType = null; return false; } commonProperties.Add(new EdmProperty(rowType1.Properties[i].Name, columnCommonTypeUsage)); } commonRowType = new RowType(commonProperties, rowType1.InitializerMetadata); return true; } private static bool TryGetCommonBaseType(EdmType type1, EdmType type2, out EdmType commonBaseType) { // put all the other base types in a dictionary Dictionary otherBaseTypes = new Dictionary (); for (EdmType ancestor = type2; ancestor != null; ancestor = ancestor.BaseType) { otherBaseTypes.Add(ancestor, 0); } // walk up the ancestor chain, and see if any of them are // common to the otherTypes ancestors for (EdmType ancestor = type1; ancestor != null; ancestor = ancestor.BaseType) { if (otherBaseTypes.ContainsKey(ancestor)) { commonBaseType = ancestor; return true; } } commonBaseType = null; return false; } private static bool HasCommonType(TypeUsage type1, TypeUsage type2) { return (null != TypeHelpers.GetCommonTypeUsage(type1, type2)); } #endregion // common super-type helpers #region Comparability /// /// Determines if the given edmType is equal comparable. Consult "EntitySql Language Specification", /// section 7 - Comparison and Dependent Operations for details. /// /// an instance of an EdmType ///true if edmType is equal-comparable, false otherwise private static bool IsEqualComparable(EdmType edmType) { if (Helper.IsPrimitiveType(edmType) || Helper.IsRefType(edmType) || Helper.IsEntityType(edmType)) { return true; } else if (Helper.IsRowType(edmType)) { RowType rowType = (RowType)edmType; foreach (EdmProperty rowProperty in rowType.Properties) { if (!IsEqualComparable(rowProperty.TypeUsage)) { return false; } } return true; } return false; } /// Determines if the given edmType is order comparable. Consult "EntitySql Language Specification", /// section 7 - Comparison and Dependent Operations for details. /// /// an instance of an EdmType ///true if edmType is order-comparable, false otherwise private static bool IsOrderComparable(EdmType edmType) { // only primitive types are assumed to be order-comparable though they // may still fail during runtime depending on the provider specific behavior return Helper.IsPrimitiveType(edmType); } #endregion #region Private Helpers private static bool CompareTypes(TypeUsage fromType, TypeUsage toType, bool equivalenceOnly) { Debug.Assert(fromType != null && toType != null); // If the type usages are the same reference, they are equal. if (object.ReferenceEquals(fromType, toType)) { return true; } if (fromType.EdmType.BuiltInTypeKind != toType.EdmType.BuiltInTypeKind) { return false; } // // Ensure structural evaluation for Collection, Ref and Row types // if (fromType.EdmType.BuiltInTypeKind == BuiltInTypeKind.CollectionType) { // Collection Type: Just compare the Element types return CompareTypes(((CollectionType)fromType.EdmType).TypeUsage, ((CollectionType)toType.EdmType).TypeUsage, equivalenceOnly); } else if (fromType.EdmType.BuiltInTypeKind == BuiltInTypeKind.RefType) { // Both are Reference Types, so compare the referenced Entity types return ((RefType)fromType.EdmType).ElementType.EdmEquals(((RefType)toType.EdmType).ElementType); } else if (fromType.EdmType.BuiltInTypeKind == BuiltInTypeKind.RowType) { // Row Types RowType fromRow = (RowType)fromType.EdmType; RowType toRow = (RowType)toType.EdmType; // Both are RowTypes, so compare the structure. // The number of properties must be the same. if (fromRow.Properties.Count != toRow.Properties.Count) { return false; } // Compare properties. For an equivalence comparison, only // property types must match, otherwise names and types must match. for (int idx = 0; idx < fromRow.Properties.Count; idx++) { EdmProperty fromProp = fromRow.Properties[idx]; EdmProperty toProp = toRow.Properties[idx]; if (!equivalenceOnly && (fromProp.Name != toProp.Name)) { return false; } if (!CompareTypes(fromProp.TypeUsage, toProp.TypeUsage, equivalenceOnly)) { return false; } } return true; } // // compare non-transient type usages - simply compare the edm types instead // return fromType.EdmType.EdmEquals(toType.EdmType); } ////// 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. /// private static void ComputeCommonTypeClosure() { if (null != _commonTypeClosure) { return; } objectModel.ReadOnlyCollection[,] commonTypeClosure = new objectModel.ReadOnlyCollection [EdmConstants.NumPrimitiveTypes, EdmConstants.NumPrimitiveTypes]; for (int i = 0; i < EdmConstants.NumPrimitiveTypes; i++) { commonTypeClosure[i, i] = Helper.EmptyPrimitiveTypeReadOnlyCollection; } objectModel.ReadOnlyCollection 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 [,]>(ref _commonTypeClosure, commonTypeClosure, null); } /// /// returns the intersection of types. /// /// /// ///private static objectModel.ReadOnlyCollection Intersect(IList types1, IList types2) { List commonTypes = new List (); for (int i = 0; i < types1.Count; i++) { if (types2.Contains(types1[i])) { commonTypes.Add(types1[i]); } } if (0 == commonTypes.Count) { return Helper.EmptyPrimitiveTypeReadOnlyCollection; } return new objectModel.ReadOnlyCollection (commonTypes); } /// /// Returns the list of common super types of two primitive types. /// /// /// ///private static objectModel.ReadOnlyCollection GetPrimitiveCommonSuperTypes(PrimitiveType primitiveType1, PrimitiveType primitiveType2) { ComputeCommonTypeClosure(); return _commonTypeClosure[(int)primitiveType1.PrimitiveTypeKind, (int)primitiveType2.PrimitiveTypeKind]; } #endregion // Private Helpers #endregion // Private interface } } // 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
- CodeMemberProperty.cs
- DataGridViewBindingCompleteEventArgs.cs
- OracleDateTime.cs
- PropertyNames.cs
- TemplateControlCodeDomTreeGenerator.cs
- FormsAuthentication.cs
- FunctionCommandText.cs
- ProcessManager.cs
- XmlSchemaSimpleTypeUnion.cs
- TcpWorkerProcess.cs
- DataGridToolTip.cs
- MailMessage.cs
- BuildResultCache.cs
- SR.cs
- GeneralTransform3DTo2D.cs
- ManagementObject.cs
- _ProxyChain.cs
- TypeBuilder.cs
- DurableInstanceProvider.cs
- RequestQueue.cs
- Function.cs
- WindowsListViewGroupHelper.cs
- CheckBoxStandardAdapter.cs
- PeerNode.cs
- ColumnReorderedEventArgs.cs
- ProtectedProviderSettings.cs
- AsymmetricKeyExchangeDeformatter.cs
- safePerfProviderHandle.cs
- VideoDrawing.cs
- followingquery.cs
- CryptoProvider.cs
- OperationFormatUse.cs
- TextCompositionEventArgs.cs
- UnsafeNativeMethods.cs
- HtmlWindowCollection.cs
- SortKey.cs
- TransformProviderWrapper.cs
- SqlMethods.cs
- BindingEntityInfo.cs
- EndpointAddress.cs
- ZipIOEndOfCentralDirectoryBlock.cs
- LoginCancelEventArgs.cs
- WebPartConnectionsCancelEventArgs.cs
- BufferedGraphicsContext.cs
- DateRangeEvent.cs
- DataGridView.cs
- NativeMethodsCLR.cs
- base64Transforms.cs
- AttachedPropertyMethodSelector.cs
- ProfileSection.cs
- EventMap.cs
- MembershipValidatePasswordEventArgs.cs
- DoubleAnimationClockResource.cs
- DetailsViewInsertEventArgs.cs
- InkCollectionBehavior.cs
- SQLMoneyStorage.cs
- DataGridComboBoxColumn.cs
- Exception.cs
- FieldDescriptor.cs
- XamlSerializer.cs
- IncrementalReadDecoders.cs
- ConnectionOrientedTransportChannelListener.cs
- ComponentCommands.cs
- TemplateModeChangedEventArgs.cs
- FlagsAttribute.cs
- TypedReference.cs
- ProcessHostMapPath.cs
- HitTestParameters3D.cs
- DesignerSerializerAttribute.cs
- DataGridViewCellMouseEventArgs.cs
- BitmapDecoder.cs
- NonSerializedAttribute.cs
- OleDbStruct.cs
- ListBoxItemAutomationPeer.cs
- XPathAncestorIterator.cs
- PreservationFileReader.cs
- UmAlQuraCalendar.cs
- MediaPlayer.cs
- KeyEventArgs.cs
- BamlCollectionHolder.cs
- AccessedThroughPropertyAttribute.cs
- XmlSiteMapProvider.cs
- HostingEnvironmentException.cs
- PassportAuthenticationModule.cs
- SecureStringHasher.cs
- CompilerLocalReference.cs
- DataGridBeginningEditEventArgs.cs
- ProjectionPlanCompiler.cs
- xsdvalidator.cs
- _NegoState.cs
- AutoGeneratedFieldProperties.cs
- DbQueryCommandTree.cs
- ProcessInputEventArgs.cs
- UserControl.cs
- XmlLanguageConverter.cs
- TypeUsage.cs
- CultureMapper.cs
- _ProxyChain.cs
- ProviderMetadataCachedInformation.cs
- RoutedEventHandlerInfo.cs