//--------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner Microsoft // @backupOwner Microsoft //--------------------------------------------------------------------- namespace System.Data.Metadata.Edm { using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.Data.Common.CommandTrees; using eSQL = System.Data.Common.EntitySql; using System.Data.Common.Utils; using System.Data.Entity; using System.Data.Mapping; using System.Data.Mapping.Update.Internal; using System.Data.Mapping.ViewGeneration; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.Versioning; using System.Xml; /// /// Runtime Metadata Workspace /// public sealed class MetadataWorkspace { #region Constructors /// /// Constructs the new instance of runtime metadata workspace /// public MetadataWorkspace() { } /// /// Create MetadataWorkspace that is populated with ItemCollections for all the spaces that the metadata artifacts provided. /// All res:// paths will be resolved only from the assemblies returned from the enumerable assembliesToConsider. /// /// The paths where the metadata artifacts located /// User specified assemblies to consider /// /// Throw when assembliesToConsider is empty or contains null, or cannot find the corresponding assembly in it /// [ResourceExposure(ResourceScope.Machine)] //Exposes the file path names which are a Machine resource [ResourceConsumption(ResourceScope.Machine)] //For MetadataWorkspace.CreateMetadataWorkspaceWithResolver method call but we do not create the file paths in this method public MetadataWorkspace(IEnumerable paths, IEnumerable assembliesToConsider) { // we are intentionally not checking to see if the paths enumerable is empty EntityUtil.CheckArgumentNull(paths, "paths"); EntityUtil.CheckArgumentContainsNull(ref paths, "paths"); EntityUtil.CheckArgumentNull(assembliesToConsider, "assembliesToConsider"); EntityUtil.CheckArgumentContainsNull(ref assembliesToConsider, "assembliesToConsider"); Func resolveReference = (AssemblyName referenceName)=> { foreach(Assembly assembly in assembliesToConsider) { if (AssemblyName.ReferenceMatchesDefinition(referenceName, new AssemblyName(assembly.FullName))) { return assembly; } } throw EntityUtil.Argument(Strings.AssemblyMissingFromAssembliesToConsider(referenceName.FullName), "assembliesToConsider"); }; CreateMetadataWorkspaceWithResolver(paths, () => assembliesToConsider, resolveReference); } [ResourceExposure(ResourceScope.Machine)] //Exposes the file path names which are a Machine resource [ResourceConsumption(ResourceScope.Machine)] //For MetadataArtifactLoader.CreateCompositeFromFilePaths method call but We do not create the file paths in this method private void CreateMetadataWorkspaceWithResolver(IEnumerable paths, Func> wildcardAssemblies, Func resolveReference) { MetadataArtifactLoader composite = MetadataArtifactLoader.CreateCompositeFromFilePaths(paths.ToArray(), "", new CustomAssemblyResolver(wildcardAssemblies, resolveReference)); // only create the ItemCollection that has corresponding artifacts DataSpace dataSpace = DataSpace.CSpace; using (DisposableCollectionWrapper cSpaceReaders = new DisposableCollectionWrapper(composite.CreateReaders(dataSpace))) { if (cSpaceReaders.Any()) { this._itemsCSpace = new EdmItemCollection(cSpaceReaders, composite.GetPaths(dataSpace)); } } dataSpace = DataSpace.SSpace; using (DisposableCollectionWrapper sSpaceReaders = new DisposableCollectionWrapper(composite.CreateReaders(dataSpace))) { if (sSpaceReaders.Any()) { this._itemsSSpace = new StoreItemCollection(sSpaceReaders, composite.GetPaths(dataSpace)); } } dataSpace = DataSpace.CSSpace; using (DisposableCollectionWrapper csSpaceReaders = new DisposableCollectionWrapper(composite.CreateReaders(dataSpace))) { if (csSpaceReaders.Any() && null != this._itemsCSpace && null != this._itemsSSpace) { this._itemsCSSpace = new StorageMappingItemCollection(this._itemsCSpace, this._itemsSSpace, csSpaceReaders, composite.GetPaths(dataSpace)); } } } #endregion #region Fields private EdmItemCollection _itemsCSpace; private StoreItemCollection _itemsSSpace; private ObjectItemCollection _itemsOSpace; private StorageMappingItemCollection _itemsCSSpace; private DefaultObjectMappingItemCollection _itemsOCSpace; private List _cacheTokens; private bool _foundAssemblyWithAttribute = false; private double _schemaVersion = XmlConstants.UndefinedVersion; private Guid _metadataWorkspaceId = Guid.Empty; #endregion #region public static Fields [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] private static IEnumerable SupportedEdmVersions { get { yield return XmlConstants.UndefinedVersion; yield return XmlConstants.EdmVersionForV1; yield return XmlConstants.EdmVersionForV2; Debug.Assert(XmlConstants.SchemaVersionLatest == XmlConstants.EdmVersionForV3, "Did you add a new version?"); yield return XmlConstants.EdmVersionForV3; } } //The Max EDM version thats going to be supported by the runtime. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] public static readonly double MaximumEdmVersionSupported = SupportedEdmVersions.Last(); #endregion #region Methods /// /// Create an configured to use the data space. /// public eSQL.EntitySqlParser CreateEntitySqlParser() { return new eSQL.EntitySqlParser(new ModelPerspective(this)); } /// /// Creates a new bound to this metadata workspace based on the specified query expression. /// /// A that defines the query /// A new with the specified expression as it's property /// If is null /// If contains metadata that cannot be resolved in this metadata workspace /// If is not structurally valid because it contains unresolvable variable references public DbQueryCommandTree CreateQueryCommandTree(DbExpression query) { return new DbQueryCommandTree(this, DataSpace.CSpace, query); } /// /// Get item collection for the space. The ItemCollection is in read only mode as it is /// part of the workspace. /// /// The dataspace for the item colelction that should be returned /// The item collection for the given space /// if space argument is null /// If ItemCollection has not been registered for the space passed in [CLSCompliant(false)] public ItemCollection GetItemCollection(DataSpace dataSpace) { ItemCollection collection = GetItemCollection(dataSpace, true); return collection; } /// /// Register the item collection for the space associated with it. /// This should be done only once for a space. /// If a space already has a registered ItemCollection InvalidOperation exception is thrown /// /// The out parameter collection that needs to be filled up /// /// if collection argument is null /// If there is an ItemCollection that has already been registered for collection's space passed in [CLSCompliant(false)] public void RegisterItemCollection(ItemCollection collection) { EntityUtil.CheckArgumentNull(collection, "collection"); ItemCollection existing; try { switch (collection.DataSpace) { case DataSpace.CSpace: if (null == (existing = _itemsCSpace)) { EdmItemCollection edmCollection = (EdmItemCollection)collection; if (!MetadataWorkspace.SupportedEdmVersions.Contains(edmCollection.EdmVersion)) { throw EntityUtil.InvalidOperation( System.Data.Entity.Strings.EdmVersionNotSupportedByRuntime( edmCollection.EdmVersion, Helper.GetCommaDelimitedString( SupportedEdmVersions .Where(e => e != XmlConstants.UndefinedVersion) .Select(e => e.ToString(CultureInfo.InvariantCulture))))); } CheckAndSetItemCollectionVersionInWorkSpace(collection); _itemsCSpace = edmCollection; } break; case DataSpace.SSpace: if (null == (existing = _itemsSSpace)) { CheckAndSetItemCollectionVersionInWorkSpace(collection); _itemsSSpace = (StoreItemCollection)collection; } break; case DataSpace.OSpace: if (null == (existing = _itemsOSpace)) { _itemsOSpace = (ObjectItemCollection)collection; } break; case DataSpace.CSSpace: if (null == (existing = _itemsCSSpace)) { CheckAndSetItemCollectionVersionInWorkSpace(collection); _itemsCSSpace = (StorageMappingItemCollection)collection; } break; default: Debug.Assert(collection.DataSpace == DataSpace.OCSpace, "Invalid DataSpace Enum value: " + collection.DataSpace); if (null == (existing = _itemsOCSpace)) { _itemsOCSpace = (DefaultObjectMappingItemCollection)collection; } break; } } catch (InvalidCastException) { throw EntityUtil.InvalidCollectionForMapping(collection.DataSpace); } if (null != existing) { throw EntityUtil.ItemCollectionAlreadyRegistered(collection.DataSpace); } // Need to make sure that if the storage mapping Item collection was created with the // same instances of item collection that are registered for CSpace and SSpace if (collection.DataSpace == DataSpace.CSpace) { if (_itemsCSSpace != null && !object.ReferenceEquals(_itemsCSSpace.EdmItemCollection, collection)) { throw EntityUtil.InvalidCollectionSpecified(collection.DataSpace); } } if (collection.DataSpace == DataSpace.SSpace) { if (_itemsCSSpace != null && !object.ReferenceEquals(_itemsCSSpace.StoreItemCollection, collection)) { throw EntityUtil.InvalidCollectionSpecified(collection.DataSpace); } } if (collection.DataSpace == DataSpace.CSSpace) { if (_itemsCSpace != null && !object.ReferenceEquals(_itemsCSSpace.EdmItemCollection, _itemsCSpace)) { throw EntityUtil.InvalidCollectionSpecified(collection.DataSpace); } if (_itemsSSpace != null && !object.ReferenceEquals(_itemsCSSpace.StoreItemCollection, _itemsSSpace)) { throw EntityUtil.InvalidCollectionSpecified(collection.DataSpace); } } } /// /// /// /// private void CheckAndSetItemCollectionVersionInWorkSpace(ItemCollection itemCollectionToRegister) { double versionToRegister = XmlConstants.UndefinedVersion; string itemCollectionType = null; switch (itemCollectionToRegister.DataSpace) { case DataSpace.CSpace: versionToRegister = ((EdmItemCollection)itemCollectionToRegister).EdmVersion; itemCollectionType = "EdmItemCollection"; break; case DataSpace.SSpace: versionToRegister = ((StoreItemCollection)itemCollectionToRegister).StoreSchemaVersion; itemCollectionType = "StoreItemCollection"; break; case DataSpace.CSSpace: versionToRegister = ((StorageMappingItemCollection)itemCollectionToRegister).MappingVersion; itemCollectionType = "StorageMappingItemCollection"; break; default: // we don't care about other spaces so keep the _versionToRegister to Undefined break; } if (versionToRegister != this._schemaVersion && versionToRegister != XmlConstants.UndefinedVersion && this._schemaVersion != XmlConstants.UndefinedVersion) { Debug.Assert(itemCollectionType != null); throw EntityUtil.DifferentSchemaVersionInCollection(itemCollectionType, versionToRegister, this._schemaVersion); } else { this._schemaVersion = versionToRegister; } } /// /// Add a token for this MetadataWorkspace just so this metadata workspace holds a reference to it, this /// is for metadata caching to make the workspace marking a particular cache entry is still in used /// /// internal void AddMetadataEntryToken(object token) { if (_cacheTokens == null) { _cacheTokens = new List(); } _cacheTokens.Add(token); } /// /// Load metadata from the given assembly /// /// The assembly from which to load metadata /// thrown if assembly argument is null public void LoadFromAssembly(Assembly assembly) { LoadFromAssembly(assembly, null); } /// /// Load metadata from the given assembly /// /// The assembly from which to load metadata /// The delegate for logging the load messages /// thrown if assembly argument is null public void LoadFromAssembly(Assembly assembly, Action logLoadMessage) { EntityUtil.CheckArgumentNull(assembly, "assembly"); ObjectItemCollection collection = (ObjectItemCollection)GetItemCollection(DataSpace.OSpace); ExplicitLoadFromAssembly(assembly, collection, logLoadMessage); } private void ExplicitLoadFromAssembly(Assembly assembly, ObjectItemCollection collection, Action logLoadMessage) { ItemCollection itemCollection; if (!TryGetItemCollection(DataSpace.CSpace, out itemCollection)) { itemCollection = null; } collection.ExplicitLoadFromAssembly(assembly, (EdmItemCollection)itemCollection, logLoadMessage); } private void ImplicitLoadFromAssembly(Assembly assembly, ObjectItemCollection collection) { if (!MetadataAssemblyHelper.ShouldFilterAssembly(assembly)) { ExplicitLoadFromAssembly(assembly, collection, null); } } /// /// Implicit loading means that we are trying to help the user find the right /// assembly, but they didn't explicitly ask for it. Our Implicit rules require that /// we filter out assemblies with the Ecma or MicrosoftPublic PublicKeyToken on them /// /// Load metadata from the type's assembly into the OSpace ItemCollection. /// If type comes from known source, has Ecma or Microsoft PublicKeyToken then the type's assembly is not /// loaded, but the callingAssembly and its referenced assemblies are loaded. /// /// The type's assembly is loaded into the OSpace ItemCollection /// The assembly and its referenced assemblies to load when type is insuffiecent internal void ImplicitLoadAssemblyForType(Type type, Assembly callingAssembly) { // this exists separately from LoadFromAssembly so that we can handle generics, like IEnumerable Debug.Assert(null != type, "null type"); ItemCollection collection; if (TryGetItemCollection(DataSpace.OSpace, out collection)) { // if OSpace is not loaded - don't register ObjectItemCollection objItemCollection = (ObjectItemCollection)collection; ItemCollection edmItemCollection; TryGetItemCollection(DataSpace.CSpace, out edmItemCollection); if (!objItemCollection.ImplicitLoadAssemblyForType(type, (EdmItemCollection)edmItemCollection) && (null != callingAssembly)) { // only load from callingAssembly if all types were filtered // then loaded referenced assemblies of calling assembly // attempt automatic discovery of user types // interesting code paths are ObjectQuery, ObjectQuery, ObjectQuery // other interesting code paths are ObjectQuery>, ObjectQuery> // when assemblies is mscorlib, System.Data or System.Data.Entity // If the schema attribute is presented on the assembly or any referenced assemblies, then it is a V1 scenario that we should // strictly follow the Get all referenced assemblies rules. // If the attribute is not presented on the assembly, then we won't load the referenced ----sembly // for this callingAssembly if (ObjectItemAttributeAssemblyLoader.IsSchemaAttributePresent(callingAssembly) || (_foundAssemblyWithAttribute || MetadataAssemblyHelper.GetNonSystemReferencedAssemblies(callingAssembly).Any(a => ObjectItemAttributeAssemblyLoader.IsSchemaAttributePresent(a)))) { // cache the knowledge that we found an attribute // because it can be expesive to figure out _foundAssemblyWithAttribute = true; objItemCollection.ImplicitLoadAllReferencedAssemblies(callingAssembly, (EdmItemCollection)edmItemCollection); } else { this.ImplicitLoadFromAssembly(callingAssembly, objItemCollection); } } } } /// /// If OSpace is not loaded for the specified EntityType /// the load metadata from the callingAssembly and its referenced assemblies. /// /// The CSPace type to verify its OSpace counterpart is loaded /// The assembly and its referenced assemblies to load when type is insuffiecent internal void ImplicitLoadFromEntityType(EntityType type, Assembly callingAssembly) { // used by ObjectContext.*GetObjectByKey when the clr type is not available // so we check the OCMap to find the clr type else attempt to autoload the OSpace from callingAssembly Debug.Assert(null != type, "null type"); Map map; if (!TryGetMap(type, DataSpace.OCSpace, out map)) { // an OCMap is not exist, attempt to load OSpace to retry ImplicitLoadAssemblyForType(typeof(System.Data.Objects.DataClasses.IEntityWithKey), callingAssembly); // We do a check here to see if the type was actually found in the attempted load. ObjectItemCollection ospaceCollection = GetItemCollection(DataSpace.OSpace) as ObjectItemCollection; EdmType ospaceType; if (ospaceCollection == null || !ospaceCollection.TryGetOSpaceType(type, out ospaceType)) { throw new InvalidOperationException(System.Data.Entity.Strings.Mapping_Object_InvalidType(type.Identity)); } } } /// /// Search for an item with the given identity in the given space. /// For example, The identity for EdmType is Namespace.Name. /// /// /// /// /// /// if space argument is null /// If ItemCollection has not been registered for the space passed in /// if identity argument passed in is null /// If the ItemCollection for this space does not have an item with the given identity /// Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace public T GetItem(string identity, DataSpace dataSpace) where T:GlobalItem { ItemCollection collection = GetItemCollection(dataSpace, true); return collection.GetItem(identity, false /*ignoreCase*/); } /// /// Search for an item with the given identity in the given space. /// /// /// /// /// /// /// if identity or space argument is null public bool TryGetItem(string identity, DataSpace space, out T item ) where T:GlobalItem { item = null; ItemCollection collection = GetItemCollection(space, false); return (null != collection) && collection.TryGetItem(identity, false /*ignoreCase*/, out item); } /// /// Search for an item with the given identity in the given space. /// For example, The identity for EdmType is Namespace.Name. /// /// /// /// /// /// /// if space argument is null /// If ItemCollection has not been registered for the space passed in /// if identity argument passed in is null /// If the ItemCollection for this space does not have an item with the given identity /// Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace public T GetItem(string identity, bool ignoreCase, DataSpace dataSpace) where T : GlobalItem { ItemCollection collection = GetItemCollection(dataSpace, true); return collection.GetItem(identity, ignoreCase); } /// /// Search for an item with the given identity in the given space. /// /// /// /// /// /// /// /// if identity or space argument is null public bool TryGetItem(string identity, bool ignoreCase, DataSpace dataSpace, out T item) where T : GlobalItem { item = null; ItemCollection collection = GetItemCollection(dataSpace, false); return (null != collection) && collection.TryGetItem(identity, ignoreCase, out item); } /// /// Returns ReadOnlyCollection of the Items of the given type /// in the workspace. /// /// /// /// /// if space argument is null /// If ItemCollection has not been registered for the space passed in /// Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace public ReadOnlyCollection GetItems(DataSpace dataSpace) where T : GlobalItem { ItemCollection collection = GetItemCollection(dataSpace, true); return collection.GetItems(); } /// /// Search for a type metadata with the specified name and namespace name in the given space. /// /// name of the type /// namespace of the type /// Dataspace to search the type for /// Returns null if no match found. /// if space argument is null /// If ItemCollection has not been registered for the space passed in /// if name or namespaceName arguments passed in are null /// If the ItemCollection for this space does not have a type with the given name and namespaceName /// Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace public EdmType GetType(string name, string namespaceName, DataSpace dataSpace) { ItemCollection collection = GetItemCollection(dataSpace, true); return collection.GetType(name, namespaceName, false /*ignoreCase*/); } /// /// Search for a type metadata with the specified name and namespace name in the given space. /// /// name of the type /// namespace of the type /// Dataspace to search the type for /// The type that needs to be filled with the return value /// Returns false if no match found. /// if name, namespaceName or space argument is null public bool TryGetType(string name, string namespaceName, DataSpace dataSpace, out EdmType type) { type = null; ItemCollection collection = GetItemCollection(dataSpace, false); return (null != collection) && collection.TryGetType(name, namespaceName, false /*ignoreCase*/, out type); } /// /// Search for a type metadata with the specified name and namespace name in the given space. /// /// name of the type /// namespace of the type /// /// Dataspace to search the type for /// Returns null if no match found. /// if space argument is null /// If ItemCollection has not been registered for the space passed in /// if name or namespaceName arguments passed in are null /// If the ItemCollection for this space does not have a type with the given name and namespaceName /// Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace public EdmType GetType(string name, string namespaceName, bool ignoreCase, DataSpace dataSpace) { ItemCollection collection = GetItemCollection(dataSpace, true); return collection.GetType(name, namespaceName, ignoreCase); } /// /// Search for a type metadata with the specified name and namespace name in the given space. /// /// name of the type /// namespace of the type /// Dataspace to search the type for /// /// The type that needs to be filled with the return value /// Returns null if no match found. /// if name, namespaceName or space argument is null public bool TryGetType(string name, string namespaceName, bool ignoreCase, DataSpace dataSpace, out EdmType type) { type = null; ItemCollection collection = GetItemCollection(dataSpace, false); return (null != collection) && collection.TryGetType(name, namespaceName, ignoreCase, out type); } /// /// Get an entity container based upon the strong name of the container /// If no entity container is found, returns null, else returns the first one/// /// name of the entity container /// /// The EntityContainer /// if space argument is null /// If ItemCollection has not been registered for the space passed in /// if name argument passed in is null /// If the ItemCollection for this space does not have a EntityContainer with the given name /// Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace public EntityContainer GetEntityContainer(string name, DataSpace dataSpace) { ItemCollection collection = GetItemCollection(dataSpace, true); return collection.GetEntityContainer(name); } /// /// Get an entity container based upon the strong name of the container /// If no entity container is found, returns null, else returns the first one/// /// name of the entity container /// /// /// if either space or name arguments is null public bool TryGetEntityContainer(string name, DataSpace dataSpace, out EntityContainer entityContainer) { entityContainer = null; // null check exists in call stack, but throws for "identity" not "name" EntityUtil.GenericCheckArgumentNull(name, "name"); ItemCollection collection = GetItemCollection(dataSpace, false); return (null != collection) && collection.TryGetEntityContainer(name, out entityContainer); } /// /// Get an entity container based upon the strong name of the container /// If no entity container is found, returns null, else returns the first one/// /// name of the entity container /// true for case-insensitive lookup /// /// The EntityContainer /// if space argument is null /// If ItemCollection has not been registered for the space passed in /// if name argument passed in is null /// If the ItemCollection for this space does not have a EntityContainer with the given name /// Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace public EntityContainer GetEntityContainer(string name, bool ignoreCase, DataSpace dataSpace) { ItemCollection collection = GetItemCollection(dataSpace, true); return collection.GetEntityContainer(name, ignoreCase); } /// /// Get an entity container based upon the strong name of the container /// If no entity container is found, returns null, else returns the first one/// /// name of the entity container /// true for case-insensitive lookup /// /// /// if name or space argument is null public bool TryGetEntityContainer(string name, bool ignoreCase, DataSpace dataSpace, out EntityContainer entityContainer) { entityContainer = null; // null check exists in call stack, but throws for "identity" not "name" EntityUtil.GenericCheckArgumentNull(name, "name"); ItemCollection collection = GetItemCollection(dataSpace, false); return (null != collection) && collection.TryGetEntityContainer(name, ignoreCase, out entityContainer); } /// /// Get all the overloads of the function with the given name /// /// name of the function /// namespace of the function /// The dataspace for which we need to get the function for /// A collection of all the functions with the given name in the given data space /// if space argument is null /// if name or namespaceName argument is null /// If ItemCollection has not been registered for the space passed in /// if functionName argument passed in is null /// If the ItemCollection for this space does not have a EdmFunction with the given functionName /// If the name or namespaceName is empty /// Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace public ReadOnlyCollection GetFunctions(string name, string namespaceName, DataSpace dataSpace) { return GetFunctions(name, namespaceName, dataSpace, false /*ignoreCase*/); } /// /// Get all the overloads of the function with the given name /// /// name of the function /// namespace of the function /// The dataspace for which we need to get the function for /// true for case-insensitive lookup /// A collection of all the functions with the given name in the given data space /// if space argument is null /// if name or namespaceName argument is null /// If ItemCollection has not been registered for the space passed in /// if functionName argument passed in is null /// If the ItemCollection for this space does not have a EdmFunction with the given functionName /// If the name or namespaceName is empty /// Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace public ReadOnlyCollection GetFunctions(string name, string namespaceName, DataSpace dataSpace, bool ignoreCase) { EntityUtil.CheckStringArgument(name, "name"); EntityUtil.CheckStringArgument(namespaceName, "namespaceName"); ItemCollection collection = GetItemCollection(dataSpace, true); // Get the function with this full name, which is namespace name plus name return collection.GetFunctions(namespaceName + "." + name, ignoreCase); } /// /// Gets the function as specified by the function key. /// All parameters are assumed to be . /// /// name of the function /// namespace of the function /// types of the parameters /// true for case-insensitive lookup /// /// The function that needs to be returned /// The function as specified in the function key or null /// if name, namespaceName, parameterTypes or space argument is null internal bool TryGetFunction(string name, string namespaceName, TypeUsage[] parameterTypes, bool ignoreCase, DataSpace dataSpace, out EdmFunction function) { function = null; EntityUtil.GenericCheckArgumentNull(name, "name"); EntityUtil.GenericCheckArgumentNull(namespaceName, "namespaceName"); ItemCollection collection = GetItemCollection(dataSpace, false); // Get the function with this full name, which is namespace name plus name return (null != collection) && collection.TryGetFunction(namespaceName + "." + name, parameterTypes, ignoreCase, out function); } /// /// Get the list of primitive types for the given space /// /// dataspace for which you need the list of primitive types /// /// if space argument is null /// If ItemCollection has not been registered for the space passed in /// Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace public ReadOnlyCollection GetPrimitiveTypes(DataSpace dataSpace) { ItemCollection collection = GetItemCollection(dataSpace, true); return collection.GetItems(); } /// /// Get all the items in the data space /// /// dataspace for which you need the list of items /// /// if space argument is null /// If ItemCollection has not been registered for the space passed in /// Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace public ReadOnlyCollection GetItems(DataSpace dataSpace) { ItemCollection collection = GetItemCollection(dataSpace, true); return collection.GetItems(); } /// /// Given the canonical primitive type, get the mapping primitive type in the given dataspace /// /// primitive type kind /// dataspace in which one needs to the mapping primitive types /// The mapped scalar type /// if space argument is null /// If ItemCollection has not been registered for the space passed in /// Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace internal PrimitiveType GetMappedPrimitiveType(PrimitiveTypeKind primitiveTypeKind, DataSpace dataSpace) { ItemCollection collection = GetItemCollection(dataSpace, true); return collection.GetMappedPrimitiveType(primitiveTypeKind); } /// /// Search for a Mapping metadata with the specified type key. /// /// type /// The dataspace that the type for which map needs to be returned belongs to /// true for case-insensitive lookup /// space for which you want to get the mapped type /// /// Returns false if no match found. internal bool TryGetMap(string typeIdentity, DataSpace typeSpace, bool ignoreCase, DataSpace mappingSpace, out Map map) { map = null; ItemCollection collection = GetItemCollection(mappingSpace, false); return (null != collection) && ((MappingItemCollection)collection).TryGetMap(typeIdentity, typeSpace, ignoreCase, out map); } /// /// Search for a Mapping metadata with the specified type key. /// /// typeIdentity of the type /// The dataspace that the type for which map needs to be returned belongs to /// space for which you want to get the mapped type /// Thrown if mapping space is not valid internal Map GetMap(string identity, DataSpace typeSpace, DataSpace dataSpace) { ItemCollection collection = GetItemCollection(dataSpace, true); return ((MappingItemCollection)collection).GetMap(identity, typeSpace); } /// /// Search for a Mapping metadata with the specified type key. /// /// /// space for which you want to get the mapped type /// Thrown if mapping space is not valid internal Map GetMap(GlobalItem item, DataSpace dataSpace) { ItemCollection collection = GetItemCollection(dataSpace, true); return ((MappingItemCollection)collection).GetMap(item); } /// /// Search for a Mapping metadata with the specified type key. /// /// /// space for which you want to get the mapped type /// /// Returns false if no match found. internal bool TryGetMap(GlobalItem item, DataSpace dataSpace, out Map map) { map = null; ItemCollection collection = GetItemCollection(dataSpace, false); return (null != collection) && ((MappingItemCollection)collection).TryGetMap(item, out map); } private ItemCollection RegisterDefaultObjectMappingItemCollection() { EdmItemCollection edm = _itemsCSpace as EdmItemCollection; ObjectItemCollection obj = _itemsOSpace as ObjectItemCollection; if ((null != edm) && (null != obj)) { RegisterItemCollection(new DefaultObjectMappingItemCollection(edm, obj)); } return _itemsOCSpace; } /// /// Get item collection for the space, if registered. If returned, the ItemCollection is in read only mode as it is /// part of the workspace. /// /// The dataspace for the item collection that should be returned /// The collection registered for the specified dataspace, if any /// true if an item collection is currently registered for the specified space; otherwise false. /// if space argument is null [CLSCompliant(false)] public bool TryGetItemCollection(DataSpace dataSpace, out ItemCollection collection) { collection = GetItemCollection(dataSpace, false); return (null != collection); } /// /// Checks if the space is valid and whether the collection is registered for the given space, and if both are valid, /// then returns the itemcollection for the given space /// /// /// if true, will throw /// Thrown if required and mapping space is not valid or registered internal ItemCollection GetItemCollection(DataSpace dataSpace, bool required) { ItemCollection collection; switch (dataSpace) { case DataSpace.CSpace: collection = _itemsCSpace; break; case DataSpace.OSpace: collection = _itemsOSpace; break; case DataSpace.OCSpace: collection = _itemsOCSpace ?? RegisterDefaultObjectMappingItemCollection(); break; case DataSpace.CSSpace: collection = _itemsCSSpace; break; case DataSpace.SSpace: collection = _itemsSSpace; break; default: if (required) { Debug.Fail("Invalid DataSpace Enum value: " + dataSpace); } collection = null; break; } if (required && (null == collection)) { throw EntityUtil.NoCollectionForSpace(dataSpace); } return collection; } /// /// The method returns the OSpace structural type mapped to the specified Edm Space Type. /// If the DataSpace of the argument is not CSpace, or the mapped OSpace type /// cannot be determined, an ArgumentException is thrown. /// /// The CSpace type to look up /// The OSpace type mapped to the supplied argument [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "edm")] public StructuralType GetObjectSpaceType(StructuralType edmSpaceType) { return GetObjectSpaceType(edmSpaceType); } /// /// This method returns the OSpace structural type mapped to the specified Edm Space Type. /// If the DataSpace of the argument is not CSpace, or if the mapped OSpace type /// cannot be determined, the method returns false and sets the out parameter /// to null. /// /// The CSpace type to look up /// The OSpace type mapped to the supplied argument /// true on success, false on failure [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "edm")] public bool TryGetObjectSpaceType(StructuralType edmSpaceType, out StructuralType objectSpaceType) { return TryGetObjectSpaceType(edmSpaceType, out objectSpaceType); } /// /// The method returns the OSpace enum type mapped to the specified Edm Space Type. /// If the DataSpace of the argument is not CSpace, or the mapped OSpace type /// cannot be determined, an ArgumentException is thrown. /// /// The CSpace type to look up /// The OSpace type mapped to the supplied argument [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "edm")] public EnumType GetObjectSpaceType(EnumType edmSpaceType) { return GetObjectSpaceType(edmSpaceType); } /// /// This method returns the OSpace enum type mapped to the specified Edm Space Type. /// If the DataSpace of the argument is not CSpace, or if the mapped OSpace type /// cannot be determined, the method returns false and sets the out parameter /// to null. /// /// The CSpace type to look up /// The OSpace type mapped to the supplied argument /// true on success, false on failure [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "edm")] public bool TryGetObjectSpaceType(EnumType edmSpaceType, out EnumType objectSpaceType) { return TryGetObjectSpaceType(edmSpaceType, out objectSpaceType); } /// /// Helper method returning the OSpace enum type mapped to the specified Edm Space Type. /// If the DataSpace of the argument is not CSpace, or the mapped OSpace type /// cannot be determined, an ArgumentException is thrown. /// /// The CSpace type to look up /// The OSpace type mapped to the supplied argument /// Must be StructuralType or EnumType. private T GetObjectSpaceType(T edmSpaceType) where T : EdmType { Debug.Assert( edmSpaceType == null || edmSpaceType is StructuralType || edmSpaceType is EnumType, "Only structural or enum type expected"); T objectSpaceType; if (!this.TryGetObjectSpaceType(edmSpaceType, out objectSpaceType)) { throw EntityUtil.Argument(Strings.FailedToFindOSpaceTypeMapping(edmSpaceType.Identity)); } return objectSpaceType; } /// /// Helper method returning the OSpace structural or enum type mapped to the specified Edm Space Type. /// If the DataSpace of the argument is not CSpace, or if the mapped OSpace type /// cannot be determined, the method returns false and sets the out parameter /// to null. /// /// The CSpace type to look up /// The OSpace type mapped to the supplied argument /// true on success, false on failure /// Must be StructuralType or EnumType. private bool TryGetObjectSpaceType(T edmSpaceType, out T objectSpaceType) where T : EdmType { Debug.Assert( edmSpaceType == null || edmSpaceType is StructuralType || edmSpaceType is EnumType, "Only structural or enum type expected"); EntityUtil.CheckArgumentNull(edmSpaceType, "edmSpaceType"); if (edmSpaceType.DataSpace != DataSpace.CSpace) { throw EntityUtil.Argument(Strings.ArgumentMustBeCSpaceType, "edmSpaceType"); } objectSpaceType = null; Map map; if (this.TryGetMap(edmSpaceType, DataSpace.OCSpace, out map)) { ObjectTypeMapping ocMap = map as ObjectTypeMapping; if (ocMap != null) { objectSpaceType = (T)ocMap.ClrType; } } return objectSpaceType != null; } /// /// This method returns the Edm Space structural type mapped to the OSpace Type parameter. If the /// DataSpace of the supplied type is not OSpace, or the mapped Edm Space type cannot /// be determined, an ArgumentException is thrown. /// /// The OSpace type to look up /// The CSpace type mapped to the OSpace parameter [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] public StructuralType GetEdmSpaceType(StructuralType objectSpaceType) { return GetEdmSpaceType(objectSpaceType); } /// /// This method returns the Edm Space structural type mapped to the OSpace Type parameter. If the /// DataSpace of the supplied type is not OSpace, or the mapped Edm Space type cannot /// be determined, the method returns false and sets the out parameter to null. /// /// The OSpace type to look up /// The mapped CSpace type /// true on success, false on failure [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "edm"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] public bool TryGetEdmSpaceType(StructuralType objectSpaceType, out StructuralType edmSpaceType) { return TryGetEdmSpaceType(objectSpaceType, out edmSpaceType); } /// /// This method returns the Edm Space enum type mapped to the OSpace Type parameter. If the /// DataSpace of the supplied type is not OSpace, or the mapped Edm Space type cannot /// be determined, an ArgumentException is thrown. /// /// The OSpace type to look up /// The CSpace type mapped to the OSpace parameter [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] public EnumType GetEdmSpaceType(EnumType objectSpaceType) { return GetEdmSpaceType(objectSpaceType); } /// /// This method returns the Edm Space enum type mapped to the OSpace Type parameter. If the /// DataSpace of the supplied type is not OSpace, or the mapped Edm Space type cannot /// be determined, the method returns false and sets the out parameter to null. /// /// The OSpace type to look up /// The mapped CSpace type /// true on success, false on failure [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "edm"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] public bool TryGetEdmSpaceType(EnumType objectSpaceType, out EnumType edmSpaceType) { return TryGetEdmSpaceType(objectSpaceType, out edmSpaceType); } /// /// Helper method returning the Edm Space structural or enum type mapped to the OSpace Type parameter. If the /// DataSpace of the supplied type is not OSpace, or the mapped Edm Space type cannot /// be determined, an ArgumentException is thrown. /// /// The OSpace type to look up /// The CSpace type mapped to the OSpace parameter /// Must be StructuralType or EnumType private T GetEdmSpaceType(T objectSpaceType) where T : EdmType { Debug.Assert( objectSpaceType == null || objectSpaceType is StructuralType || objectSpaceType is EnumType, "Only structural or enum type expected"); T edmSpaceType; if (!this.TryGetEdmSpaceType(objectSpaceType, out edmSpaceType)) { throw EntityUtil.Argument(Strings.FailedToFindCSpaceTypeMapping(objectSpaceType.Identity)); } return edmSpaceType; } /// /// Helper method returning the Edm Space structural or enum type mapped to the OSpace Type parameter. If the /// DataSpace of the supplied type is not OSpace, or the mapped Edm Space type cannot /// be determined, the method returns false and sets the out parameter to null. /// /// The OSpace type to look up /// The mapped CSpace type /// true on success, false on failure /// Must be StructuralType or EnumType private bool TryGetEdmSpaceType(T objectSpaceType, out T edmSpaceType) where T : EdmType { Debug.Assert( objectSpaceType == null || objectSpaceType is StructuralType || objectSpaceType is EnumType, "Only structural or enum type expected"); EntityUtil.CheckArgumentNull(objectSpaceType, "objectSpaceType"); if (objectSpaceType.DataSpace != DataSpace.OSpace) { throw EntityUtil.Argument(Strings.ArgumentMustBeOSpaceType, "objectSpaceType"); } edmSpaceType = null; Map map; if (this.TryGetMap(objectSpaceType, DataSpace.OCSpace, out map)) { ObjectTypeMapping ocMap = map as ObjectTypeMapping; if (ocMap != null) { edmSpaceType = (T)ocMap.EdmType; } } return edmSpaceType != null; } ///// ///// Returns the update or query view for an Extent as a ///// command tree. For a given Extent, MetadataWorkspace will ///// have either a Query view or an Update view but not both. ///// ///// ///// internal DbQueryCommandTree GetCqtView(EntitySetBase extent) { return GetGeneratedView(extent).GetCommandTree(); } /// /// Returns generated update or query view for the given extent. /// internal GeneratedView GetGeneratedView(EntitySetBase extent) { ItemCollection collection = GetItemCollection(DataSpace.CSSpace, true); return ((StorageMappingItemCollection)collection).GetGeneratedView(extent, this); } /// /// Returns a TypeOf/TypeOfOnly Query for a given Extent and Type as a command tree. /// /// /// internal bool TryGetGeneratedViewOfType(EntitySetBase extent, EntityTypeBase type, bool includeSubtypes, out GeneratedView generatedView) { ItemCollection collection = GetItemCollection(DataSpace.CSSpace, true); return ((StorageMappingItemCollection)collection).TryGetGeneratedViewOfType(this, extent, type, includeSubtypes, out generatedView); } /// /// Returns generated function definition for the given function. /// Guarantees type match of declaration and generated parameters. /// Guarantees return type match. /// Throws internal error for functions without definition. /// Passes thru exception occured during definition generation. /// internal DbLambda GetGeneratedFunctionDefinition(EdmFunction function) { ItemCollection collection = GetItemCollection(DataSpace.CSpace, true); return ((EdmItemCollection)collection).GetGeneratedFunctionDefinition(function); } /// /// Determines if a target function exists for the given function import. /// /// Function import (function declared in a model entity container) /// Function target mapping (function to which the import is mapped in the target store) /// true if a mapped target function exists; false otherwise internal bool TryGetFunctionImportMapping(EdmFunction functionImport, out FunctionImportMapping targetFunctionMapping) { Debug.Assert(null != functionImport); ReadOnlyCollection entityContainerMaps = this.GetItems(DataSpace.CSSpace); foreach (StorageEntityContainerMapping containerMapping in entityContainerMaps) { if (containerMapping.TryGetFunctionImportMapping(functionImport, out targetFunctionMapping)) { return true; } } targetFunctionMapping = null; return false; } /// /// Returns the view loader associated with this workspace, /// creating a loader if non exists. The loader includes /// context information used by the update pipeline when /// processing changes to C-space extents. /// /// internal ViewLoader GetUpdateViewLoader() { if (_itemsCSSpace != null) { return _itemsCSSpace.GetUpdateViewLoader(); } return null; } /// /// Takes in a Edm space type usage and converts into an /// equivalent O space type usage /// /// /// internal TypeUsage GetOSpaceTypeUsage(TypeUsage edmSpaceTypeUsage) { EntityUtil.CheckArgumentNull(edmSpaceTypeUsage, "edmSpaceTypeUsage"); Debug.Assert(edmSpaceTypeUsage.EdmType != null, "The TypeUsage object does not have an EDMType."); EdmType clrType = null; if (Helper.IsPrimitiveType(edmSpaceTypeUsage.EdmType)) { ItemCollection collection = GetItemCollection(DataSpace.OSpace, true); clrType = collection.GetMappedPrimitiveType(((PrimitiveType)edmSpaceTypeUsage.EdmType).PrimitiveTypeKind); } else { // Check and throw if the OC space doesn't exist ItemCollection collection = GetItemCollection(DataSpace.OCSpace, true); // Get the OC map Map map = ((DefaultObjectMappingItemCollection)collection).GetMap(edmSpaceTypeUsage.EdmType); clrType = ((ObjectTypeMapping)map).ClrType; } Debug.Assert(!Helper.IsPrimitiveType(clrType) || object.ReferenceEquals(ClrProviderManifest.Instance.GetFacetDescriptions(clrType), EdmProviderManifest.Instance.GetFacetDescriptions(clrType.BaseType)), "these are no longer equal so we can't just use the same set of facets for the new type usage"); // Transfer the facet values TypeUsage result = TypeUsage.Create(clrType, edmSpaceTypeUsage.Facets); return result; } /// /// Returns true if the item collection for the given space has already been registered else returns false /// /// /// internal bool IsItemCollectionAlreadyRegistered(DataSpace dataSpace) { ItemCollection itemCollection; return TryGetItemCollection(dataSpace, out itemCollection); } /// /// Requires: C, S and CS are registered in this and other /// Determines whether C, S and CS are equivalent. Useful in determining whether a DbCommandTree /// is usable within a particular entity connection. /// /// Other workspace. /// true is C, S and CS collections are equivalent internal bool IsMetadataWorkspaceCSCompatible(MetadataWorkspace other) { Debug.Assert(this.IsItemCollectionAlreadyRegistered(DataSpace.CSSpace) && other.IsItemCollectionAlreadyRegistered(DataSpace.CSSpace), "requires: C, S and CS are registered in this and other"); bool result = this._itemsCSSpace.MetadataEquals(other._itemsCSSpace); Debug.Assert(!result || (this._itemsCSpace.MetadataEquals(other._itemsCSpace) && this._itemsSSpace.MetadataEquals(other._itemsSSpace)), "constraint: this.CS == other.CS --> this.S == other.S && this.C == other.C"); return result; } /// /// Clear all the metadata cache entries /// public static void ClearCache() { MetadataCache.Clear(); ObjectItemCollection.ViewGenerationAssemblies.Clear(); using (LockedAssemblyCache cache = AssemblyCache.AquireLockedAssemblyCache()) { cache.Clear(); } } /// /// Creates a new Metadata workspace sharing the (currently defined) item collections /// and tokens for caching purposes. /// /// internal MetadataWorkspace ShallowCopy() { MetadataWorkspace copy = (MetadataWorkspace)MemberwiseClone(); if (null != copy._cacheTokens) { copy._cacheTokens = new List(copy._cacheTokens); } return copy; } /// /// Returns the canonical Model TypeUsage for a given PrimitiveTypeKind /// /// PrimitiveTypeKind for which a canonical TypeUsage is expected /// a canonical model TypeUsage internal TypeUsage GetCanonicalModelTypeUsage(PrimitiveTypeKind primitiveTypeKind) { return EdmProviderManifest.Instance.GetCanonicalModelTypeUsage(primitiveTypeKind); } /// /// Returns the Model PrimitiveType for a given primitiveTypeKind /// /// a PrimitiveTypeKind for which a Model PrimitiveType is expected /// Model PrimitiveType internal PrimitiveType GetModelPrimitiveType(PrimitiveTypeKind primitiveTypeKind) { return EdmProviderManifest.Instance.GetPrimitiveType(primitiveTypeKind); } // GetRequiredOriginalValueMembers and GetRelevantMembersForUpdate return list of "interesting" members for the given EntitySet/EntityType // Interesting Members are a subset of the following: // 0. Key members // 1. Members with C-Side conditions (complex types can not have C-side condition at present) // 2. Members participating in association end // 3. Members with ConcurrencyMode 'Fixed' // 3.1 Complex Members with any child member having Concurrency mode Fixed // 4. Members included in Update ModificationFunction with Version='Original' (Original = Not Current) // 4.1 Complex Members in ModificationFunction if any sub-member is interesting // 5. Members included in Update ModificationFunction (mutually exclusive with 4 - required for partial update scenarios) // 6. Foreign keys // 7. All complex members - partial update scenarios only /// /// Returns members of a given EntitySet/EntityType for which original values are necessary for determining which tables to modify. /// /// An EntitySet belonging to the C-Space /// An EntityType that participates in the given EntitySet /// Edm Members for which original Value is required /// /// This method returns the following groups of members: 0, 1, 2, 3, 3.1, 4, 4.1. (see group descriptions above). /// This method is marked as obsolete since it does not support partial update scenarios as it does not return /// members from group 5 and changing it to return these members would be a breaking change. /// [Obsolete("Use MetadataWorkspace.GetRelevantMembersForUpdate(EntitySetBase, EntityTypeBase, bool) instead")] public IEnumerable GetRequiredOriginalValueMembers(EntitySetBase entitySet, EntityTypeBase entityType) { return GetInterestingMembers(entitySet, entityType, StorageMappingItemCollection.InterestingMembersKind.RequiredOriginalValueMembers); } /// /// Returns members of a given EntitySet/EntityType for which original values are needed when modifying an entity. /// /// An EntitySet belonging to the C-Space /// An EntityType that participates in the given EntitySet /// Whether entities may be updated partially. /// Edm Members for which original Value is required /// /// This method returns the following groups of members: /// - if is false: 1, 2, 3, 3.1, 4, 4.1, 6 (see group descriptions above) /// - if is true: 1, 2, 3, 3.1, 5, 6, 7 (see group descriptions above) /// See DevDiv bugs #124460 and #272992 for more details. /// public ReadOnlyCollection GetRelevantMembersForUpdate(EntitySetBase entitySet, EntityTypeBase entityType, bool partialUpdateSupported) { return GetInterestingMembers( entitySet, entityType, partialUpdateSupported ? StorageMappingItemCollection.InterestingMembersKind.PartialUpdate : StorageMappingItemCollection.InterestingMembersKind.FullUpdate); } /// /// Return members for and methods. /// /// An EntitySet belonging to the C-Space /// An EntityType that participates in the given EntitySet /// Scenario the members should be returned for. /// ReadOnlyCollection of interesting members for the requested scenario (). private ReadOnlyCollection GetInterestingMembers(EntitySetBase entitySet, EntityTypeBase entityType, StorageMappingItemCollection.InterestingMembersKind interestingMembersKind) { EntityUtil.CheckArgumentNull(entitySet, "entitySet"); EntityUtil.CheckArgumentNull(entityType, "entityType"); Debug.Assert(entitySet.EntityContainer != null); //Check that EntitySet is from CSpace if (entitySet.EntityContainer.DataSpace != DataSpace.CSpace) { AssociationSet associationSet = entitySet as AssociationSet; if (associationSet != null) { throw EntityUtil.AssociationSetNotInCSpace(entitySet.Name); } else { throw EntityUtil.EntitySetNotInCSpace(entitySet.Name); } } //Check that entityType belongs to entitySet if (!entitySet.ElementType.IsAssignableFrom(entityType)) { AssociationSet associationSet = entitySet as AssociationSet; if (associationSet != null) { throw EntityUtil.TypeNotInAssociationSet(entitySet.Name, entitySet.ElementType.FullName, entityType.FullName); } else { throw EntityUtil.TypeNotInEntitySet(entitySet.Name, entitySet.ElementType.FullName, entityType.FullName); } } var mappingCollection = (StorageMappingItemCollection)GetItemCollection(DataSpace.CSSpace, true); return mappingCollection.GetInterestingMembers(entitySet, entityType, interestingMembersKind); } #endregion #region Properties /// /// Returns the QueryCacheManager hosted by this metadata workspace instance /// internal System.Data.Common.QueryCache.QueryCacheManager GetQueryCacheManager() { Debug.Assert(null != _itemsSSpace, "_itemsSSpace must not be null"); return _itemsSSpace.QueryCacheManager; } internal Guid MetadataWorkspaceId { get { if (Guid.Equals(Guid.Empty, _metadataWorkspaceId)) { _metadataWorkspaceId = Guid.NewGuid(); } return _metadataWorkspaceId; } } #endregion } }