831428feee1da3738d8632fb95606c4af04fd2ce
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Metadata / MetadataWorkspace.cs
1 //---------------------------------------------------------------------
2 // <copyright file="MetadataWorkspace.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9
10 namespace System.Data.Metadata.Edm
11 {
12     using System;
13     using System.Collections.Generic;
14     using System.Collections.ObjectModel;
15     using System.Data;
16     using System.Data.Common.CommandTrees;
17     using eSQL = System.Data.Common.EntitySql;
18     using System.Data.Common.Utils;
19     using System.Data.Entity;
20     using System.Data.Mapping;
21     using System.Data.Mapping.Update.Internal;
22     using System.Data.Mapping.ViewGeneration;
23     using System.Diagnostics;
24     using System.Globalization;
25     using System.Linq;
26     using System.Reflection;
27     using System.Runtime.Versioning;
28     using System.Xml;
29
30     /// <summary>
31     /// Runtime Metadata Workspace
32     /// </summary>
33     public sealed class MetadataWorkspace
34     {
35         #region Constructors
36         /// <summary>
37         /// Constructs the new instance of runtime metadata workspace
38         /// </summary>
39         public MetadataWorkspace()
40         {
41         }
42
43         /// <summary>
44         /// Create MetadataWorkspace that is populated with ItemCollections for all the spaces that the metadata artifacts provided.
45         /// All res:// paths will be resolved only from the assemblies returned from the enumerable assembliesToConsider.
46         /// </summary>
47         /// <param name="paths">The paths where the metadata artifacts located</param>
48         /// <param name="assembliesToConsider">User specified assemblies to consider</param>
49         /// <exception cref="ArgumentNullException"></exception>
50         /// <exception cref="ArgumentException">Throw when assembliesToConsider is empty or contains null, or cannot find the corresponding assembly in it</exception>
51         /// <exception cref="MetadataException"></exception>
52         [ResourceExposure(ResourceScope.Machine)] //Exposes the file path names which are a Machine resource
53         [ResourceConsumption(ResourceScope.Machine)] //For MetadataWorkspace.CreateMetadataWorkspaceWithResolver method call but we do not create the file paths in this method 
54         public MetadataWorkspace(IEnumerable<string> paths, IEnumerable<Assembly> assembliesToConsider)
55         {
56             // we are intentionally not checking to see if the paths enumerable is empty
57             EntityUtil.CheckArgumentNull(paths, "paths");
58             EntityUtil.CheckArgumentContainsNull(ref paths, "paths");
59
60             EntityUtil.CheckArgumentNull(assembliesToConsider, "assembliesToConsider");
61             EntityUtil.CheckArgumentContainsNull(ref assembliesToConsider, "assembliesToConsider");
62
63             Func<AssemblyName, Assembly> resolveReference = (AssemblyName referenceName)=>
64             {
65                 foreach(Assembly assembly in assembliesToConsider)
66                 {
67                     if (AssemblyName.ReferenceMatchesDefinition(referenceName, new AssemblyName(assembly.FullName)))
68                     {
69                         return assembly;
70                     }
71                 }
72                 throw EntityUtil.Argument(Strings.AssemblyMissingFromAssembliesToConsider(referenceName.FullName), "assembliesToConsider");
73             };
74
75
76             CreateMetadataWorkspaceWithResolver(paths, () => assembliesToConsider, resolveReference);
77         }
78
79         [ResourceExposure(ResourceScope.Machine)] //Exposes the file path names which are a Machine resource
80         [ResourceConsumption(ResourceScope.Machine)] //For MetadataArtifactLoader.CreateCompositeFromFilePaths method call but We do not create the file paths in this method 
81         private void CreateMetadataWorkspaceWithResolver(IEnumerable<string> paths, Func<IEnumerable<Assembly>> wildcardAssemblies, Func<AssemblyName, Assembly> resolveReference)
82         {
83             MetadataArtifactLoader composite = MetadataArtifactLoader.CreateCompositeFromFilePaths(paths.ToArray(), "", new CustomAssemblyResolver(wildcardAssemblies, resolveReference));
84
85             // only create the ItemCollection that has corresponding artifacts
86             DataSpace dataSpace = DataSpace.CSpace;
87             using (DisposableCollectionWrapper<XmlReader> cSpaceReaders = new DisposableCollectionWrapper<XmlReader>(composite.CreateReaders(dataSpace)))
88             {
89                 if (cSpaceReaders.Any())
90                 {
91                     this._itemsCSpace = new EdmItemCollection(cSpaceReaders, composite.GetPaths(dataSpace));
92                 }
93             }
94
95             dataSpace = DataSpace.SSpace;
96             using (DisposableCollectionWrapper<XmlReader> sSpaceReaders = new DisposableCollectionWrapper<XmlReader>(composite.CreateReaders(dataSpace)))
97             {
98                 if (sSpaceReaders.Any())
99                 {
100                     this._itemsSSpace = new StoreItemCollection(sSpaceReaders, composite.GetPaths(dataSpace));
101                 }
102             }
103
104             dataSpace = DataSpace.CSSpace;
105             using (DisposableCollectionWrapper<XmlReader> csSpaceReaders = new DisposableCollectionWrapper<XmlReader>(composite.CreateReaders(dataSpace)))
106             {
107                 if (csSpaceReaders.Any() && null != this._itemsCSpace && null != this._itemsSSpace)
108                 {
109                     this._itemsCSSpace = new StorageMappingItemCollection(this._itemsCSpace, this._itemsSSpace, csSpaceReaders, composite.GetPaths(dataSpace));
110                 }
111             }
112         }
113         #endregion
114
115         #region Fields
116         private EdmItemCollection _itemsCSpace;
117         private StoreItemCollection _itemsSSpace;
118         private ObjectItemCollection _itemsOSpace;
119         private StorageMappingItemCollection _itemsCSSpace;
120         private DefaultObjectMappingItemCollection _itemsOCSpace;
121
122         private List<object> _cacheTokens;
123         private bool _foundAssemblyWithAttribute = false;
124         private double _schemaVersion = XmlConstants.UndefinedVersion;
125         private Guid _metadataWorkspaceId = Guid.Empty;
126         #endregion
127
128         #region public static Fields
129         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")]
130         private static IEnumerable<double> SupportedEdmVersions
131         {
132             get
133             {
134                 yield return XmlConstants.UndefinedVersion;
135                 yield return XmlConstants.EdmVersionForV1;
136                 yield return XmlConstants.EdmVersionForV2;
137                 Debug.Assert(XmlConstants.SchemaVersionLatest == XmlConstants.EdmVersionForV3, "Did you add a new version?");
138                 yield return XmlConstants.EdmVersionForV3;
139             }
140         }
141         //The Max EDM version thats going to be supported by the runtime.
142         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")]
143         public static readonly double MaximumEdmVersionSupported = SupportedEdmVersions.Last();
144         #endregion
145
146         #region Methods
147         /// <summary>
148         /// Create an <see cref="eSQL.EntitySqlParser"/> configured to use the <see cref="DataSpace.CSpace"/> data space.
149         /// </summary>
150         public eSQL.EntitySqlParser CreateEntitySqlParser()
151         {
152             return new eSQL.EntitySqlParser(new ModelPerspective(this));
153         }
154
155         /// <summary>
156         /// Creates a new <see cref="DbQueryCommandTree"/> bound to this metadata workspace based on the specified query expression.
157         /// </summary>
158         /// <param name="query">A <see cref="DbExpression"/> that defines the query</param>
159         /// <returns>A new <see cref="DbQueryCommandTree"/> with the specified expression as it's <see cref="DbQueryCommandTree.Query"/> property</returns>
160         /// <exception cref="ArgumentNullException">If <paramref name="query"/> is null</exception>
161         /// <exception cref="ArgumentException">If <paramref name="query"/> contains metadata that cannot be resolved in this metadata workspace</exception>
162         /// <exception cref="ArgumentException">If <paramref name="query"/> is not structurally valid because it contains unresolvable variable references</exception>
163         public DbQueryCommandTree CreateQueryCommandTree(DbExpression query)
164         {
165             return new DbQueryCommandTree(this, DataSpace.CSpace, query);
166         }
167
168         /// <summary>
169         /// Get item collection for the space. The ItemCollection is in read only mode as it is
170         /// part of the workspace.
171         /// </summary>
172         /// <param name="dataSpace">The dataspace for the item colelction that should be returned</param>
173         /// <returns>The item collection for the given space</returns>
174         /// <exception cref="System.ArgumentNullException">if space argument is null</exception>
175         /// <exception cref="System.InvalidOperationException">If ItemCollection has not been registered for the space passed in</exception>
176         [CLSCompliant(false)]
177         public ItemCollection GetItemCollection(DataSpace dataSpace)
178         {
179             ItemCollection collection = GetItemCollection(dataSpace, true);
180             return collection;
181         }
182
183         /// <summary>
184         /// Register the item collection for the space associated with it.
185         /// This should be done only once for a space.
186         /// If a space already has a registered ItemCollection InvalidOperation exception is thrown
187         /// </summary>
188         /// <param name="collection">The out parameter collection that needs to be filled up</param>
189         /// <returns></returns>
190         /// <exception cref="System.ArgumentNullException">if collection argument is null</exception>
191         /// <exception cref="System.InvalidOperationException">If there is an ItemCollection that has already been registered for collection's space passed in</exception>
192         [CLSCompliant(false)]
193         public void RegisterItemCollection(ItemCollection collection)
194         {
195             EntityUtil.CheckArgumentNull(collection, "collection");
196
197             ItemCollection existing;
198             
199             try
200             {
201                 switch (collection.DataSpace)
202                 {
203                 case DataSpace.CSpace:
204                     if (null == (existing = _itemsCSpace)) {
205                         EdmItemCollection edmCollection = (EdmItemCollection)collection;
206                         if (!MetadataWorkspace.SupportedEdmVersions.Contains(edmCollection.EdmVersion))
207                         {
208
209                             throw EntityUtil.InvalidOperation(
210                                 System.Data.Entity.Strings.EdmVersionNotSupportedByRuntime(
211                                 edmCollection.EdmVersion, 
212                                 Helper.GetCommaDelimitedString(
213                                     SupportedEdmVersions
214                                         .Where(e => e != XmlConstants.UndefinedVersion)
215                                         .Select(e => e.ToString(CultureInfo.InvariantCulture)))));
216                         }
217
218                         CheckAndSetItemCollectionVersionInWorkSpace(collection);
219
220                         _itemsCSpace = edmCollection;
221                     }
222                     break;
223                 case DataSpace.SSpace:
224                     if (null == (existing = _itemsSSpace))
225                     {
226                         CheckAndSetItemCollectionVersionInWorkSpace(collection);
227                         _itemsSSpace = (StoreItemCollection)collection;
228                     }
229                     break;
230                 case DataSpace.OSpace:
231                     if (null == (existing = _itemsOSpace)) {
232                         _itemsOSpace = (ObjectItemCollection)collection;
233                     }
234                     break;
235                 case DataSpace.CSSpace:
236                     if (null == (existing = _itemsCSSpace)) {
237                         CheckAndSetItemCollectionVersionInWorkSpace(collection);
238                         _itemsCSSpace = (StorageMappingItemCollection)collection;
239                     }
240                     break;
241                 default:
242                     Debug.Assert(collection.DataSpace == DataSpace.OCSpace, "Invalid DataSpace Enum value: " + collection.DataSpace);
243                     
244                     if (null == (existing = _itemsOCSpace)) {
245                         _itemsOCSpace = (DefaultObjectMappingItemCollection)collection;
246                     }
247                     break;
248                 }
249             }
250             catch (InvalidCastException)
251             {
252                 throw EntityUtil.InvalidCollectionForMapping(collection.DataSpace);
253             }
254             if (null != existing)
255             {
256                 throw EntityUtil.ItemCollectionAlreadyRegistered(collection.DataSpace);
257             }
258             // Need to make sure that if the storage mapping Item collection was created with the 
259             // same instances of item collection that are registered for CSpace and SSpace
260             if (collection.DataSpace == DataSpace.CSpace)
261             {
262                 if (_itemsCSSpace != null && !object.ReferenceEquals(_itemsCSSpace.EdmItemCollection, collection))
263                 {
264                     throw EntityUtil.InvalidCollectionSpecified(collection.DataSpace);
265                 }
266             }
267
268             if (collection.DataSpace == DataSpace.SSpace)
269             {
270                 if (_itemsCSSpace != null && !object.ReferenceEquals(_itemsCSSpace.StoreItemCollection, collection))
271                 {
272                     throw EntityUtil.InvalidCollectionSpecified(collection.DataSpace);
273                 }
274             }
275
276             if (collection.DataSpace == DataSpace.CSSpace)
277             {
278                 if (_itemsCSpace != null && !object.ReferenceEquals(_itemsCSSpace.EdmItemCollection, _itemsCSpace))
279                 {
280                     throw EntityUtil.InvalidCollectionSpecified(collection.DataSpace);
281                 }
282
283                 if (_itemsSSpace != null && !object.ReferenceEquals(_itemsCSSpace.StoreItemCollection, _itemsSSpace))
284                 {
285                     throw EntityUtil.InvalidCollectionSpecified(collection.DataSpace);
286                 }
287             }
288         }
289
290         /// <summary>
291         /// 
292         /// </summary>
293         /// <param name="itemCollectionToRegister"></param>
294         private void CheckAndSetItemCollectionVersionInWorkSpace(ItemCollection itemCollectionToRegister)
295         {
296             double versionToRegister = XmlConstants.UndefinedVersion;
297             string itemCollectionType = null;
298             switch (itemCollectionToRegister.DataSpace)
299             {
300                 case DataSpace.CSpace:
301                     versionToRegister = ((EdmItemCollection)itemCollectionToRegister).EdmVersion;
302                     itemCollectionType = "EdmItemCollection";
303                     break;
304                 case DataSpace.SSpace:
305                     versionToRegister = ((StoreItemCollection)itemCollectionToRegister).StoreSchemaVersion;
306                     itemCollectionType = "StoreItemCollection";
307                     break;
308                 case DataSpace.CSSpace:
309                     versionToRegister = ((StorageMappingItemCollection)itemCollectionToRegister).MappingVersion;
310                     itemCollectionType = "StorageMappingItemCollection";
311                     break;
312                 default:
313                     // we don't care about other spaces so keep the _versionToRegister to Undefined
314                     break;
315             }
316
317             if (versionToRegister != this._schemaVersion && 
318                 versionToRegister != XmlConstants.UndefinedVersion && 
319                 this._schemaVersion != XmlConstants.UndefinedVersion)
320             {
321                 Debug.Assert(itemCollectionType != null);
322                 throw EntityUtil.DifferentSchemaVersionInCollection(itemCollectionType, versionToRegister, this._schemaVersion);
323             }
324             else
325             {
326                 this._schemaVersion = versionToRegister;
327             }
328         }
329         /// <summary>
330         /// Add a token for this MetadataWorkspace just so this metadata workspace holds a reference to it, this
331         /// is for metadata caching to make the workspace marking a particular cache entry is still in used
332         /// </summary>
333         /// <param name="token"></param>
334         internal void AddMetadataEntryToken(object token)
335         {
336             if (_cacheTokens == null)
337             {
338                 _cacheTokens = new List<object>();
339             }
340
341             _cacheTokens.Add(token);
342         }
343
344         /// <summary>
345         /// Load metadata from the given assembly
346         /// </summary>
347         /// <param name="assembly">The assembly from which to load metadata</param>
348         /// <exception cref="System.ArgumentNullException">thrown if assembly argument is null</exception>
349         public void LoadFromAssembly(Assembly assembly)
350         {
351             LoadFromAssembly(assembly, null);
352         }
353
354         /// <summary>
355         /// Load metadata from the given assembly
356         /// </summary>
357         /// <param name="assembly">The assembly from which to load metadata</param>
358         /// <param name="logLoadMessage">The delegate for logging the load messages</param>
359         /// <exception cref="System.ArgumentNullException">thrown if assembly argument is null</exception>
360         public void LoadFromAssembly(Assembly assembly, Action<string> logLoadMessage)
361         {
362             EntityUtil.CheckArgumentNull(assembly, "assembly");
363             ObjectItemCollection collection = (ObjectItemCollection)GetItemCollection(DataSpace.OSpace);
364             ExplicitLoadFromAssembly(assembly, collection, logLoadMessage);
365         }
366
367         private void ExplicitLoadFromAssembly(Assembly assembly, ObjectItemCollection collection, Action<string> logLoadMessage)
368         {
369             ItemCollection itemCollection;
370             if (!TryGetItemCollection(DataSpace.CSpace, out itemCollection))
371             {
372                 itemCollection = null;
373             }
374
375             collection.ExplicitLoadFromAssembly(assembly, (EdmItemCollection)itemCollection, logLoadMessage);
376         }
377
378         private void ImplicitLoadFromAssembly(Assembly assembly, ObjectItemCollection collection)
379         {
380             if (!MetadataAssemblyHelper.ShouldFilterAssembly(assembly))
381             {
382                 ExplicitLoadFromAssembly(assembly, collection, null);
383             }
384         }
385
386         /// <summary>
387         /// Implicit loading means that we are trying to help the user find the right 
388         /// assembly, but they didn't explicitly ask for it. Our Implicit rules require that
389         /// we filter out assemblies with the Ecma or MicrosoftPublic PublicKeyToken on them
390         /// 
391         /// Load metadata from the type's assembly into the OSpace ItemCollection.
392         /// If type comes from known source, has Ecma or Microsoft PublicKeyToken then the type's assembly is not
393         /// loaded, but the callingAssembly and its referenced assemblies are loaded.
394         /// </summary>
395         /// <param name="type">The type's assembly is loaded into the OSpace ItemCollection</param>
396         /// <param name="callingAssembly">The assembly and its referenced assemblies to load when type is insuffiecent</param>
397         internal void ImplicitLoadAssemblyForType(Type type, Assembly callingAssembly)
398         {
399             // this exists separately from LoadFromAssembly so that we can handle generics, like IEnumerable<Product>
400             Debug.Assert(null != type, "null type");
401             ItemCollection collection;
402             if (TryGetItemCollection(DataSpace.OSpace, out collection))
403             {   // if OSpace is not loaded - don't register
404                 ObjectItemCollection objItemCollection = (ObjectItemCollection)collection;
405                 ItemCollection edmItemCollection;
406                 TryGetItemCollection(DataSpace.CSpace, out edmItemCollection);
407                 if (!objItemCollection.ImplicitLoadAssemblyForType(type, (EdmItemCollection)edmItemCollection) && (null != callingAssembly))
408                 {
409                     // only load from callingAssembly if all types were filtered
410                     // then loaded referenced assemblies of calling assembly
411
412                     // attempt automatic discovery of user types
413                     // interesting code paths are ObjectQuery<object>, ObjectQuery<DbDataRecord>, ObjectQuery<IExtendedDataRecord>
414                     // other interesting code paths are ObjectQuery<Nullable<Int32>>, ObjectQuery<IEnumerable<object>>
415                     // when assemblies is mscorlib, System.Data or System.Data.Entity
416                     
417                             // If the schema attribute is presented on the assembly or any referenced assemblies, then it is a V1 scenario that we should
418                     // strictly follow the Get all referenced assemblies rules.
419                     // If the attribute is not presented on the assembly, then we won't load the referenced ----sembly 
420                     // for this callingAssembly
421                     if (ObjectItemAttributeAssemblyLoader.IsSchemaAttributePresent(callingAssembly) ||
422                         (_foundAssemblyWithAttribute || 
423                           MetadataAssemblyHelper.GetNonSystemReferencedAssemblies(callingAssembly).Any(a => ObjectItemAttributeAssemblyLoader.IsSchemaAttributePresent(a))))
424                     {
425                         // cache the knowledge that we found an attribute
426                         // because it can be expesive to figure out
427                         _foundAssemblyWithAttribute = true;
428                         objItemCollection.ImplicitLoadAllReferencedAssemblies(callingAssembly, (EdmItemCollection)edmItemCollection);
429                     }
430                     else
431                     {
432                         this.ImplicitLoadFromAssembly(callingAssembly, objItemCollection);
433                     }
434                 }
435             }
436         }
437
438         /// <summary>
439         /// If OSpace is not loaded for the specified EntityType
440         /// the load metadata from the callingAssembly and its referenced assemblies.
441         /// </summary>
442         /// <param name="type">The CSPace type to verify its OSpace counterpart is loaded</param>
443         /// <param name="callingAssembly">The assembly and its referenced assemblies to load when type is insuffiecent</param>
444         internal void ImplicitLoadFromEntityType(EntityType type, Assembly callingAssembly)
445         {
446            // used by ObjectContext.*GetObjectByKey when the clr type is not available
447            // so we check the OCMap to find the clr type else attempt to autoload the OSpace from callingAssembly
448             Debug.Assert(null != type, "null type");
449             Map map;
450             if (!TryGetMap(type, DataSpace.OCSpace, out map))
451             {   // an OCMap is not exist, attempt to load OSpace to retry
452                 ImplicitLoadAssemblyForType(typeof(System.Data.Objects.DataClasses.IEntityWithKey), callingAssembly);
453
454                 // We do a check here to see if the type was actually found in the attempted load.
455                 ObjectItemCollection ospaceCollection = GetItemCollection(DataSpace.OSpace) as ObjectItemCollection;
456                 EdmType ospaceType;
457                 if (ospaceCollection == null || !ospaceCollection.TryGetOSpaceType(type, out ospaceType))
458                 {
459                     throw new InvalidOperationException(System.Data.Entity.Strings.Mapping_Object_InvalidType(type.Identity));
460                 }
461             }
462         }
463
464         /// <summary>
465         /// Search for an item with the given identity in the given space.
466         /// For example, The identity for EdmType is Namespace.Name.
467         /// </summary>
468         /// <typeparam name="T"></typeparam>
469         /// <param name="identity"></param>
470         /// <param name="dataSpace"></param>
471         /// <returns></returns>
472         /// <exception cref="System.ArgumentNullException">if space argument is null</exception>
473         /// <exception cref="System.InvalidOperationException">If ItemCollection has not been registered for the space passed in</exception>
474         /// <exception cref="System.ArgumentNullException">if identity argument passed in is null</exception>
475         /// <exception cref="System.ArgumentException">If the ItemCollection for this space does not have an item with the given identity</exception>
476         /// <exception cref="System.ArgumentException">Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace</exception>
477         public T GetItem<T>(string identity, DataSpace dataSpace) where T:GlobalItem
478         {
479             ItemCollection collection = GetItemCollection(dataSpace, true);
480             return collection.GetItem<T>(identity, false /*ignoreCase*/);
481         }
482
483         /// <summary>
484         /// Search for an item with the given identity in the given space.
485         /// </summary>
486         /// <typeparam name="T"></typeparam>
487         /// <param name="identity"></param>
488         /// <param name="space"></param>
489         /// <param name="item"></param>
490         /// <returns></returns>
491         /// <exception cref="System.ArgumentNullException">if identity or space argument is null</exception>
492         public bool TryGetItem<T>(string identity, DataSpace space, out T item ) where T:GlobalItem
493         {
494             item = null;
495             ItemCollection collection = GetItemCollection(space, false);
496             return (null != collection) && collection.TryGetItem<T>(identity, false /*ignoreCase*/, out item);
497         }
498
499         /// <summary>
500         /// Search for an item with the given identity in the given space.
501         /// For example, The identity for EdmType is Namespace.Name.
502         /// </summary>
503         /// <typeparam name="T"></typeparam>
504         /// <param name="identity"></param>
505         /// <param name="ignoreCase"></param>
506         /// <param name="dataSpace"></param>
507         /// <returns></returns>
508         /// <exception cref="System.ArgumentNullException">if space argument is null</exception>
509         /// <exception cref="System.InvalidOperationException">If ItemCollection has not been registered for the space passed in</exception>
510         /// <exception cref="System.ArgumentNullException">if identity argument passed in is null</exception>
511         /// <exception cref="System.ArgumentException">If the ItemCollection for this space does not have an item with the given identity</exception>
512         /// <exception cref="System.ArgumentException">Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace</exception>
513         public T GetItem<T>(string identity, bool ignoreCase, DataSpace dataSpace) where T : GlobalItem
514         {
515             ItemCollection collection = GetItemCollection(dataSpace, true);
516             return collection.GetItem<T>(identity, ignoreCase);
517         }
518
519         /// <summary>
520         /// Search for an item with the given identity in the given space.
521         /// </summary>
522         /// <typeparam name="T"></typeparam>
523         /// <param name="ignoreCase"></param>
524         /// <param name="identity"></param>
525         /// <param name="dataSpace"></param>
526         /// <param name="item"></param>
527         /// <returns></returns>
528         /// <exception cref="System.ArgumentNullException">if identity or space argument is null</exception>
529         public bool TryGetItem<T>(string identity, bool ignoreCase, DataSpace dataSpace, out T item) where T : GlobalItem
530         {
531             item = null;
532             ItemCollection collection = GetItemCollection(dataSpace, false);
533             return (null != collection) && collection.TryGetItem<T>(identity, ignoreCase, out item);
534         }
535
536         /// <summary>
537         /// Returns ReadOnlyCollection of the Items of the given type
538         /// in the workspace.
539         /// </summary>
540         /// <typeparam name="T"></typeparam>
541         /// <param name="dataSpace"></param>
542         /// <returns></returns>
543         /// <exception cref="System.ArgumentNullException">if space argument is null</exception>
544         /// <exception cref="System.InvalidOperationException">If ItemCollection has not been registered for the space passed in</exception>
545         /// <exception cref="System.ArgumentException">Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace</exception>
546         public ReadOnlyCollection<T> GetItems<T>(DataSpace dataSpace) where T : GlobalItem
547         {
548             ItemCollection collection = GetItemCollection(dataSpace, true);
549             return collection.GetItems<T>();
550         }
551
552         /// <summary>
553         /// Search for a type metadata with the specified name and namespace name in the given space.
554         /// </summary>
555         /// <param name="name">name of the type</param>
556         /// <param name="namespaceName">namespace of the type</param>
557         /// <param name="dataSpace">Dataspace to search the type for</param>
558         /// <returns>Returns null if no match found.</returns>
559         /// <exception cref="System.ArgumentNullException">if space argument is null</exception>
560         /// <exception cref="System.InvalidOperationException">If ItemCollection has not been registered for the space passed in</exception>
561         /// <exception cref="System.ArgumentNullException">if name or namespaceName arguments passed in are null</exception>
562         /// <exception cref="System.ArgumentException">If the ItemCollection for this space does not have a type with the given name and namespaceName</exception>
563         /// <exception cref="System.ArgumentException">Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace</exception>
564         public EdmType GetType(string name, string namespaceName, DataSpace dataSpace)
565         {
566             ItemCollection collection = GetItemCollection(dataSpace, true);
567             return collection.GetType(name, namespaceName, false /*ignoreCase*/);
568         }
569
570         /// <summary>
571         /// Search for a type metadata with the specified name and namespace name in the given space.
572         /// </summary>
573         /// <param name="name">name of the type</param>
574         /// <param name="namespaceName">namespace of the type</param>
575         /// <param name="dataSpace">Dataspace to search the type for</param>
576         /// <param name="type">The type that needs to be filled with the return value</param>
577         /// <returns>Returns false if no match found.</returns>
578         /// <exception cref="System.ArgumentNullException">if name, namespaceName or space argument is null</exception>
579         public bool TryGetType(string name, string namespaceName, DataSpace dataSpace, out EdmType type)
580         {
581             type = null;
582             ItemCollection collection = GetItemCollection(dataSpace, false);
583             return (null != collection) && collection.TryGetType(name, namespaceName, false /*ignoreCase*/, out type);
584         }
585
586
587
588         /// <summary>
589         /// Search for a type metadata with the specified name and namespace name in the given space.
590         /// </summary>
591         /// <param name="name">name of the type</param>
592         /// <param name="namespaceName">namespace of the type</param>
593         /// <param name="ignoreCase"></param>
594         /// <param name="dataSpace">Dataspace to search the type for</param>
595         /// <returns>Returns null if no match found.</returns>
596         /// <exception cref="System.ArgumentNullException">if space argument is null</exception>
597         /// <exception cref="System.InvalidOperationException">If ItemCollection has not been registered for the space passed in</exception>
598         /// <exception cref="System.ArgumentNullException">if name or namespaceName arguments passed in are null</exception>
599         /// <exception cref="System.ArgumentException">If the ItemCollection for this space does not have a type with the given name and namespaceName</exception>
600         /// <exception cref="System.ArgumentException">Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace</exception>
601         public EdmType GetType(string name, string namespaceName, bool ignoreCase, DataSpace dataSpace)
602         {
603             ItemCollection collection = GetItemCollection(dataSpace, true);
604             return collection.GetType(name, namespaceName, ignoreCase);
605         }
606
607         /// <summary>
608         /// Search for a type metadata with the specified name and namespace name in the given space.
609         /// </summary>
610         /// <param name="name">name of the type</param>
611         /// <param name="namespaceName">namespace of the type</param>
612         /// <param name="dataSpace">Dataspace to search the type for</param>
613         /// <param name="ignoreCase"></param>
614         /// <param name="type">The type that needs to be filled with the return value</param>
615         /// <returns>Returns null if no match found.</returns>
616         /// <exception cref="System.ArgumentNullException">if name, namespaceName or space argument is null</exception>
617         public bool TryGetType(string name, string namespaceName, bool ignoreCase,
618                                DataSpace dataSpace, out EdmType type)
619         {
620             type = null;
621             ItemCollection collection = GetItemCollection(dataSpace, false);
622             return (null != collection) && collection.TryGetType(name, namespaceName, ignoreCase, out type);
623         }
624
625
626         /// <summary>
627         /// Get an entity container based upon the strong name of the container
628         /// If no entity container is found, returns null, else returns the first one/// </summary>
629         /// <param name="name">name of the entity container</param>
630         /// <param name="dataSpace"></param>
631         /// <returns>The EntityContainer</returns>
632         /// <exception cref="System.ArgumentNullException">if space argument is null</exception>
633         /// <exception cref="System.InvalidOperationException">If ItemCollection has not been registered for the space passed in</exception>
634         /// <exception cref="System.ArgumentNullException">if name argument passed in is null</exception>
635         /// <exception cref="System.ArgumentException">If the ItemCollection for this space does not have a EntityContainer with the given name</exception>
636         /// <exception cref="System.ArgumentException">Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace</exception>
637         public EntityContainer GetEntityContainer(string name, DataSpace dataSpace)
638         {
639             ItemCollection collection = GetItemCollection(dataSpace, true);
640             return collection.GetEntityContainer(name);
641         }
642
643         /// <summary>
644         /// Get an entity container based upon the strong name of the container
645         /// If no entity container is found, returns null, else returns the first one/// </summary>
646         /// <param name="name">name of the entity container</param>
647         /// <param name="dataSpace"></param>
648         /// <param name="entityContainer"></param>
649         /// <exception cref="System.ArgumentNullException">if either space or name arguments is null</exception>
650         public bool TryGetEntityContainer(string name, DataSpace dataSpace, out EntityContainer entityContainer)
651         {
652             entityContainer = null;
653             // null check exists in call stack, but throws for "identity" not "name"
654             EntityUtil.GenericCheckArgumentNull(name, "name");
655             ItemCollection collection = GetItemCollection(dataSpace, false);
656             return (null != collection) && collection.TryGetEntityContainer(name, out entityContainer);
657         }
658
659         /// <summary>
660         /// Get an entity container based upon the strong name of the container
661         /// If no entity container is found, returns null, else returns the first one/// </summary>
662         /// <param name="name">name of the entity container</param>
663         /// <param name="ignoreCase">true for case-insensitive lookup</param>
664         /// <param name="dataSpace"></param>
665         /// <returns>The EntityContainer</returns>
666         /// <exception cref="System.ArgumentNullException">if space argument is null</exception>
667         /// <exception cref="System.InvalidOperationException">If ItemCollection has not been registered for the space passed in</exception>
668         /// <exception cref="System.ArgumentNullException">if name argument passed in is null</exception>
669         /// <exception cref="System.ArgumentException">If the ItemCollection for this space does not have a EntityContainer with the given name</exception>
670         /// <exception cref="System.ArgumentException">Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace</exception>
671         public EntityContainer GetEntityContainer(string name, bool ignoreCase, DataSpace dataSpace)
672         {
673             ItemCollection collection = GetItemCollection(dataSpace, true);
674             return collection.GetEntityContainer(name, ignoreCase);
675         }
676
677         /// <summary>
678         /// Get an entity container based upon the strong name of the container
679         /// If no entity container is found, returns null, else returns the first one/// </summary>
680         /// <param name="name">name of the entity container</param>
681         /// <param name="ignoreCase">true for case-insensitive lookup</param>
682         /// <param name="dataSpace"></param>
683         /// <param name="entityContainer"></param>
684         /// <exception cref="System.ArgumentNullException">if name or space argument is null</exception>
685         public bool TryGetEntityContainer(string name, bool ignoreCase,
686                                                              DataSpace dataSpace, out EntityContainer entityContainer)
687         {
688             entityContainer = null;
689             // null check exists in call stack, but throws for "identity" not "name"
690             EntityUtil.GenericCheckArgumentNull(name, "name");
691             ItemCollection collection = GetItemCollection(dataSpace, false);
692             return (null != collection) && collection.TryGetEntityContainer(name, ignoreCase, out entityContainer);
693         }
694
695         /// <summary>
696         /// Get all the overloads of the function with the given name
697         /// </summary>
698         /// <param name="name">name of the function</param>
699         /// <param name="namespaceName">namespace of the function</param>
700         /// <param name="dataSpace">The dataspace for which we need to get the function for</param>
701         /// <returns>A collection of all the functions with the given name in the given data space</returns>
702         /// <exception cref="System.ArgumentNullException">if space argument is null</exception>
703         /// <exception cref="System.ArgumentNullException">if name or namespaceName argument is null</exception>
704         /// <exception cref="System.InvalidOperationException">If ItemCollection has not been registered for the space passed in</exception>
705         /// <exception cref="System.ArgumentNullException">if functionName argument passed in is null</exception>
706         /// <exception cref="System.ArgumentException">If the ItemCollection for this space does not have a EdmFunction with the given functionName</exception>
707         /// <exception cref="System.ArgumentException">If the name or namespaceName is empty</exception>
708         /// <exception cref="System.ArgumentException">Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace</exception>
709         public ReadOnlyCollection<EdmFunction> GetFunctions(string name, string namespaceName, DataSpace dataSpace)
710         {
711             return GetFunctions(name, namespaceName, dataSpace, false /*ignoreCase*/);
712         }
713
714         /// <summary>
715         /// Get all the overloads of the function with the given name
716         /// </summary>
717         /// <param name="name">name of the function</param>
718         /// <param name="namespaceName">namespace of the function</param>
719         /// <param name="dataSpace">The dataspace for which we need to get the function for</param>
720         /// <param name="ignoreCase">true for case-insensitive lookup</param>
721         /// <returns>A collection of all the functions with the given name in the given data space</returns>
722         /// <exception cref="System.ArgumentNullException">if space argument is null</exception>
723         /// <exception cref="System.ArgumentNullException">if name or namespaceName argument is null</exception>
724         /// <exception cref="System.InvalidOperationException">If ItemCollection has not been registered for the space passed in</exception>
725         /// <exception cref="System.ArgumentNullException">if functionName argument passed in is null</exception>
726         /// <exception cref="System.ArgumentException">If the ItemCollection for this space does not have a EdmFunction with the given functionName</exception>
727         /// <exception cref="System.ArgumentException">If the name or namespaceName is empty</exception>
728         /// <exception cref="System.ArgumentException">Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace</exception>
729         public ReadOnlyCollection<EdmFunction> GetFunctions(string name,
730                                                             string namespaceName,
731                                                             DataSpace dataSpace,
732                                                             bool ignoreCase)
733         {
734             EntityUtil.CheckStringArgument(name, "name");
735             EntityUtil.CheckStringArgument(namespaceName, "namespaceName");
736             ItemCollection collection = GetItemCollection(dataSpace, true);
737
738             // Get the function with this full name, which is namespace name plus name
739             return collection.GetFunctions(namespaceName + "." + name, ignoreCase);
740         }
741
742         /// <summary>
743         /// Gets the function as specified by the function key.
744         /// All parameters are assumed to be <see cref="ParameterMode.In"/>.
745         /// </summary>
746         /// <param name="name">name of the function</param>
747         /// <param name="namespaceName">namespace of the function</param>
748         /// <param name="parameterTypes">types of the parameters</param>
749         /// <param name="ignoreCase">true for case-insensitive lookup</param>
750         /// <param name="dataSpace"></param>
751         /// <param name="function">The function that needs to be returned</param>
752         /// <returns> The function as specified in the function key or null</returns>
753         /// <exception cref="System.ArgumentNullException">if name, namespaceName, parameterTypes or space argument is null</exception>
754         internal bool TryGetFunction(string name,
755                                      string namespaceName,
756                                      TypeUsage[] parameterTypes,
757                                      bool ignoreCase,
758                                      DataSpace dataSpace,
759                                      out EdmFunction function)
760         {
761             function = null;
762             EntityUtil.GenericCheckArgumentNull(name, "name");
763             EntityUtil.GenericCheckArgumentNull(namespaceName, "namespaceName");
764             ItemCollection collection = GetItemCollection(dataSpace, false);
765
766             // Get the function with this full name, which is namespace name plus name
767             return (null != collection) && collection.TryGetFunction(namespaceName + "." + name, parameterTypes, ignoreCase, out function);
768         }
769
770         /// <summary>
771         /// Get the list of primitive types for the given space
772         /// </summary>
773         /// <param name="dataSpace">dataspace for which you need the list of primitive types</param>
774         /// <returns></returns>
775         /// <exception cref="System.ArgumentNullException">if space argument is null</exception>
776         /// <exception cref="System.InvalidOperationException">If ItemCollection has not been registered for the space passed in</exception>
777         /// <exception cref="System.ArgumentException">Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace</exception>
778         public ReadOnlyCollection<PrimitiveType> GetPrimitiveTypes(DataSpace dataSpace)
779         {
780             ItemCollection collection = GetItemCollection(dataSpace, true);
781             return collection.GetItems<PrimitiveType>();
782         }
783
784         /// <summary>
785         /// Get all the items in the data space
786         /// </summary>
787         /// <param name="dataSpace">dataspace for which you need the list of items</param>
788         /// <returns></returns>
789         /// <exception cref="System.ArgumentNullException">if space argument is null</exception>
790         /// <exception cref="System.InvalidOperationException">If ItemCollection has not been registered for the space passed in</exception>
791         /// <exception cref="System.ArgumentException">Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace</exception>
792         public ReadOnlyCollection<GlobalItem> GetItems(DataSpace dataSpace)
793         {
794             ItemCollection collection = GetItemCollection(dataSpace, true);
795             return collection.GetItems<GlobalItem>();
796         }
797
798         /// <summary>
799         /// Given the canonical primitive type, get the mapping primitive type in the given dataspace
800         /// </summary>
801         /// <param name="primitiveTypeKind">primitive type kind</param>
802         /// <param name="dataSpace">dataspace in which one needs to the mapping primitive types</param>
803         /// <returns>The mapped scalar type</returns>
804         /// <exception cref="System.ArgumentNullException">if space argument is null</exception>
805         /// <exception cref="System.InvalidOperationException">If ItemCollection has not been registered for the space passed in</exception>
806         /// <exception cref="System.ArgumentException">Thrown if the space is not a valid space. Valid space is either C, O, CS or OCSpace</exception>
807         internal PrimitiveType GetMappedPrimitiveType(PrimitiveTypeKind primitiveTypeKind, DataSpace dataSpace)
808         {
809             ItemCollection collection = GetItemCollection(dataSpace, true);
810             return collection.GetMappedPrimitiveType(primitiveTypeKind);
811         }
812
813         /// <summary>
814         /// Search for a Mapping metadata with the specified type key.
815         /// </summary>
816         /// <param name="typeIdentity">type</param>
817         /// <param name="typeSpace">The dataspace that the type for which map needs to be returned belongs to</param>
818         /// <param name="ignoreCase">true for case-insensitive lookup</param>
819         /// <param name="mappingSpace">space for which you want to get the mapped type</param>
820         /// <param name="map"></param>
821         /// <returns>Returns false if no match found.</returns>
822         internal bool TryGetMap(string typeIdentity, DataSpace typeSpace, bool ignoreCase, DataSpace mappingSpace, out Map map)
823         {
824             map = null;
825             ItemCollection collection = GetItemCollection(mappingSpace, false);
826             return (null != collection) && ((MappingItemCollection)collection).TryGetMap(typeIdentity, typeSpace, ignoreCase, out map);
827         }
828
829         /// <summary>
830         /// Search for a Mapping metadata with the specified type key.
831         /// </summary>
832         /// <param name="identity">typeIdentity of the type</param>
833         /// <param name="typeSpace">The dataspace that the type for which map needs to be returned belongs to</param>
834         /// <param name="dataSpace">space for which you want to get the mapped type</param>
835         /// <exception cref="ArgumentException"> Thrown if mapping space is not valid</exception>
836         internal Map GetMap(string identity, DataSpace typeSpace, DataSpace dataSpace)
837         {
838             ItemCollection collection = GetItemCollection(dataSpace, true);
839             return ((MappingItemCollection)collection).GetMap(identity, typeSpace);
840         }
841
842         /// <summary>
843         /// Search for a Mapping metadata with the specified type key.
844         /// </summary>
845         /// <param name="item"></param>
846         /// <param name="dataSpace">space for which you want to get the mapped type</param>
847         /// <exception cref="ArgumentException"> Thrown if mapping space is not valid</exception>
848         internal Map GetMap(GlobalItem item, DataSpace dataSpace)
849         {
850             ItemCollection collection = GetItemCollection(dataSpace, true);
851             return ((MappingItemCollection)collection).GetMap(item);
852         }
853
854         /// <summary>
855         /// Search for a Mapping metadata with the specified type key.
856         /// </summary>
857         /// <param name="item"></param>
858         /// <param name="dataSpace">space for which you want to get the mapped type</param>
859         /// <param name="map"></param>
860         /// <returns>Returns false if no match found.</returns>
861         internal bool TryGetMap(GlobalItem item, DataSpace dataSpace, out Map map)
862         {
863             map = null;
864             ItemCollection collection = GetItemCollection(dataSpace, false);
865             return (null != collection) && ((MappingItemCollection)collection).TryGetMap(item, out map);
866         }
867
868         private ItemCollection RegisterDefaultObjectMappingItemCollection()
869         {
870             EdmItemCollection edm = _itemsCSpace as EdmItemCollection;
871             ObjectItemCollection obj = _itemsOSpace as ObjectItemCollection;
872             if ((null != edm) && (null != obj))
873             {
874                 RegisterItemCollection(new DefaultObjectMappingItemCollection(edm, obj));
875             }
876             return _itemsOCSpace;
877         }
878
879         /// <summary>
880         /// Get item collection for the space, if registered. If returned, the ItemCollection is in read only mode as it is
881         /// part of the workspace.
882         /// </summary>
883         /// <param name="dataSpace">The dataspace for the item collection that should be returned</param>
884         /// <param name="collection">The collection registered for the specified dataspace, if any</param>
885         /// <returns><c>true</c> if an item collection is currently registered for the specified space; otherwise <c>false</c>.</returns>
886         /// <exception cref="System.ArgumentNullException">if space argument is null</exception>
887         [CLSCompliant(false)]
888         public bool TryGetItemCollection(DataSpace dataSpace, out ItemCollection collection)
889         {
890             collection = GetItemCollection(dataSpace, false);
891             return (null != collection);
892         }
893
894         /// <summary>
895         /// Checks if the space is valid and whether the collection is registered for the given space, and if both are valid,
896         /// then returns the itemcollection for the given space
897         /// </summary>
898         /// <param name="dataSpace"></param>
899         /// <param name="required">if true, will throw</param>
900         /// <exception cref="ArgumentException">Thrown if required and mapping space is not valid or registered</exception>
901         internal ItemCollection GetItemCollection(DataSpace dataSpace, bool required)
902         {
903             ItemCollection collection;
904             switch (dataSpace)
905             {
906             case DataSpace.CSpace:
907                 collection = _itemsCSpace;
908                 break;
909             case DataSpace.OSpace:
910                 collection = _itemsOSpace;
911                 break;
912             case DataSpace.OCSpace:
913                 collection = _itemsOCSpace ?? RegisterDefaultObjectMappingItemCollection();
914                 break;
915             case DataSpace.CSSpace:
916                 collection = _itemsCSSpace;
917                 break;
918             case DataSpace.SSpace:
919                 collection = _itemsSSpace;
920                 break;
921             default:
922                 if (required) {
923                     Debug.Fail("Invalid DataSpace Enum value: " + dataSpace);
924                 }
925                 collection = null;
926                 break;
927             }
928             if (required && (null == collection)) {
929                 throw EntityUtil.NoCollectionForSpace(dataSpace);
930             }
931             return collection;
932         }
933
934         /// <summary>
935         /// The method returns the OSpace structural type mapped to the specified Edm Space Type.
936         /// If the DataSpace of the argument is not CSpace, or the mapped OSpace type 
937         /// cannot be determined, an ArgumentException is thrown.
938         /// </summary>
939         /// <param name="edmSpaceType">The CSpace type to look up</param>
940         /// <returns>The OSpace type mapped to the supplied argument</returns>
941         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "edm")]
942         public StructuralType GetObjectSpaceType(StructuralType edmSpaceType)
943         {
944             return GetObjectSpaceType<StructuralType>(edmSpaceType);
945         }
946
947         /// <summary>
948         /// This method returns the OSpace structural type mapped to the specified Edm Space Type.
949         /// If the DataSpace of the argument is not CSpace, or if the mapped OSpace type 
950         /// cannot be determined, the method returns false and sets the out parameter
951         /// to null.
952         /// </summary>
953         /// <param name="edmSpaceType">The CSpace type to look up</param>
954         /// <param name="objectSpaceType">The OSpace type mapped to the supplied argument</param>
955         /// <returns>true on success, false on failure</returns>
956         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "edm")]
957         public bool TryGetObjectSpaceType(StructuralType edmSpaceType, out StructuralType objectSpaceType)
958         {
959             return TryGetObjectSpaceType<StructuralType>(edmSpaceType, out objectSpaceType);
960         }
961
962         /// <summary>
963         /// The method returns the OSpace enum type mapped to the specified Edm Space Type.
964         /// If the DataSpace of the argument is not CSpace, or the mapped OSpace type 
965         /// cannot be determined, an ArgumentException is thrown.
966         /// </summary>
967         /// <param name="edmSpaceType">The CSpace type to look up</param>
968         /// <returns>The OSpace type mapped to the supplied argument</returns>
969         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "edm")]
970         public EnumType GetObjectSpaceType(EnumType edmSpaceType)
971         {
972             return GetObjectSpaceType<EnumType>(edmSpaceType);
973         }
974
975         /// <summary>
976         /// This method returns the OSpace enum type mapped to the specified Edm Space Type.
977         /// If the DataSpace of the argument is not CSpace, or if the mapped OSpace type 
978         /// cannot be determined, the method returns false and sets the out parameter
979         /// to null.
980         /// </summary>
981         /// <param name="edmSpaceType">The CSpace type to look up</param>
982         /// <param name="objectSpaceType">The OSpace type mapped to the supplied argument</param>
983         /// <returns>true on success, false on failure</returns>
984         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "edm")]
985         public bool TryGetObjectSpaceType(EnumType edmSpaceType, out EnumType objectSpaceType)
986         {
987             return TryGetObjectSpaceType<EnumType>(edmSpaceType, out objectSpaceType);
988         }
989
990         /// <summary>
991         /// Helper method returning the OSpace enum type mapped to the specified Edm Space Type.
992         /// If the DataSpace of the argument is not CSpace, or the mapped OSpace type 
993         /// cannot be determined, an ArgumentException is thrown.
994         /// </summary>
995         /// <param name="edmSpaceType">The CSpace type to look up</param>
996         /// <returns>The OSpace type mapped to the supplied argument</returns>
997         /// <typeparam name="T">Must be StructuralType or EnumType.</typeparam>
998         private T GetObjectSpaceType<T>(T edmSpaceType)
999             where T : EdmType
1000         {
1001             Debug.Assert(
1002                 edmSpaceType == null || edmSpaceType is StructuralType || edmSpaceType is EnumType,
1003                 "Only structural or enum type expected");
1004
1005             T objectSpaceType;
1006             if (!this.TryGetObjectSpaceType(edmSpaceType, out objectSpaceType))
1007             {
1008                 throw EntityUtil.Argument(Strings.FailedToFindOSpaceTypeMapping(edmSpaceType.Identity));
1009             }
1010
1011             return objectSpaceType;
1012         }
1013
1014         /// <summary>
1015         /// Helper method returning the OSpace structural or enum type mapped to the specified Edm Space Type.
1016         /// If the DataSpace of the argument is not CSpace, or if the mapped OSpace type 
1017         /// cannot be determined, the method returns false and sets the out parameter
1018         /// to null.
1019         /// </summary>
1020         /// <param name="edmSpaceType">The CSpace type to look up</param>
1021         /// <param name="objectSpaceType">The OSpace type mapped to the supplied argument</param>
1022         /// <returns>true on success, false on failure</returns>
1023         /// <typeparam name="T">Must be StructuralType or EnumType.</typeparam>
1024         private bool TryGetObjectSpaceType<T>(T edmSpaceType, out T objectSpaceType)
1025             where T : EdmType
1026         {
1027             Debug.Assert(
1028                 edmSpaceType == null || edmSpaceType is StructuralType || edmSpaceType is EnumType,
1029                 "Only structural or enum type expected");
1030
1031             EntityUtil.CheckArgumentNull(edmSpaceType, "edmSpaceType");
1032
1033             if (edmSpaceType.DataSpace != DataSpace.CSpace)
1034             {
1035                 throw EntityUtil.Argument(Strings.ArgumentMustBeCSpaceType, "edmSpaceType");
1036             }
1037
1038             objectSpaceType = null;
1039
1040             Map map;
1041             if (this.TryGetMap(edmSpaceType, DataSpace.OCSpace, out map))
1042             {
1043                 ObjectTypeMapping ocMap = map as ObjectTypeMapping;
1044                 if (ocMap != null)
1045                 {
1046                     objectSpaceType = (T)ocMap.ClrType;
1047                 }
1048             }
1049
1050             return objectSpaceType != null;
1051         }
1052
1053         /// <summary>
1054         /// This method returns the Edm Space structural type mapped to the OSpace Type parameter. If the
1055         /// DataSpace of the supplied type is not OSpace, or the mapped Edm Space type cannot
1056         /// be determined, an ArgumentException is thrown.
1057         /// </summary>
1058         /// <param name="objectSpaceType">The OSpace type to look up</param>
1059         /// <returns>The CSpace type mapped to the OSpace parameter</returns>
1060         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")]
1061         public StructuralType GetEdmSpaceType(StructuralType objectSpaceType)
1062         {
1063             return GetEdmSpaceType<StructuralType>(objectSpaceType);
1064         }
1065
1066         /// <summary>
1067         /// This method returns the Edm Space structural type mapped to the OSpace Type parameter. If the
1068         /// DataSpace of the supplied type is not OSpace, or the mapped Edm Space type cannot
1069         /// be determined, the method returns false and sets the out parameter to null.
1070         /// </summary>
1071         /// <param name="objectSpaceType">The OSpace type to look up</param>
1072         /// <param name="edmSpaceType">The mapped CSpace type</param>
1073         /// <returns>true on success, false on failure</returns>
1074         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "edm"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")]
1075         public bool TryGetEdmSpaceType(StructuralType objectSpaceType, out StructuralType edmSpaceType)
1076         {
1077             return TryGetEdmSpaceType<StructuralType>(objectSpaceType, out edmSpaceType);
1078         }
1079
1080         /// <summary>
1081         /// This method returns the Edm Space enum type mapped to the OSpace Type parameter. If the
1082         /// DataSpace of the supplied type is not OSpace, or the mapped Edm Space type cannot
1083         /// be determined, an ArgumentException is thrown.
1084         /// </summary>
1085         /// <param name="objectSpaceType">The OSpace type to look up</param>
1086         /// <returns>The CSpace type mapped to the OSpace parameter</returns>
1087         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")]        
1088         public EnumType GetEdmSpaceType(EnumType objectSpaceType)
1089         {
1090             return GetEdmSpaceType<EnumType>(objectSpaceType);
1091         }
1092
1093         /// <summary>
1094         /// This method returns the Edm Space enum type mapped to the OSpace Type parameter. If the
1095         /// DataSpace of the supplied type is not OSpace, or the mapped Edm Space type cannot
1096         /// be determined, the method returns false and sets the out parameter to null.
1097         /// </summary>
1098         /// <param name="objectSpaceType">The OSpace type to look up</param>
1099         /// <param name="edmSpaceType">The mapped CSpace type</param>
1100         /// <returns>true on success, false on failure</returns>
1101         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "edm"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")]        
1102         public bool TryGetEdmSpaceType(EnumType objectSpaceType, out EnumType edmSpaceType)
1103         {
1104             return TryGetEdmSpaceType<EnumType>(objectSpaceType, out edmSpaceType);
1105         }
1106
1107         /// <summary>
1108         /// Helper method returning the Edm Space structural or enum type mapped to the OSpace Type parameter. If the
1109         /// DataSpace of the supplied type is not OSpace, or the mapped Edm Space type cannot
1110         /// be determined, an ArgumentException is thrown.
1111         /// </summary>
1112         /// <param name="objectSpaceType">The OSpace type to look up</param>
1113         /// <returns>The CSpace type mapped to the OSpace parameter</returns>
1114         /// <typeparam name="T">Must be StructuralType or EnumType</typeparam>
1115         private T GetEdmSpaceType<T>(T objectSpaceType)
1116             where T : EdmType
1117         {
1118             Debug.Assert(
1119                 objectSpaceType == null || objectSpaceType is StructuralType || objectSpaceType is EnumType,
1120                 "Only structural or enum type expected");
1121
1122             T edmSpaceType;
1123             if (!this.TryGetEdmSpaceType(objectSpaceType, out edmSpaceType))
1124             {
1125                 throw EntityUtil.Argument(Strings.FailedToFindCSpaceTypeMapping(objectSpaceType.Identity));
1126             }
1127
1128             return edmSpaceType;
1129         }
1130
1131         /// <summary>
1132         /// Helper method returning the Edm Space structural or enum type mapped to the OSpace Type parameter. If the
1133         /// DataSpace of the supplied type is not OSpace, or the mapped Edm Space type cannot
1134         /// be determined, the method returns false and sets the out parameter to null.
1135         /// </summary>
1136         /// <param name="objectSpaceType">The OSpace type to look up</param>
1137         /// <param name="edmSpaceType">The mapped CSpace type</param>
1138         /// <returns>true on success, false on failure</returns>
1139         /// <typeparam name="T">Must be StructuralType or EnumType</typeparam>
1140         private bool TryGetEdmSpaceType<T>(T objectSpaceType, out T edmSpaceType)
1141             where T : EdmType
1142         {
1143             Debug.Assert(
1144                 objectSpaceType == null || objectSpaceType is StructuralType || objectSpaceType is EnumType,
1145                 "Only structural or enum type expected");
1146
1147             EntityUtil.CheckArgumentNull(objectSpaceType, "objectSpaceType");
1148
1149             if (objectSpaceType.DataSpace != DataSpace.OSpace)
1150             {
1151                 throw EntityUtil.Argument(Strings.ArgumentMustBeOSpaceType, "objectSpaceType");
1152             }
1153
1154             edmSpaceType = null;
1155
1156             Map map;
1157             if (this.TryGetMap(objectSpaceType, DataSpace.OCSpace, out map))
1158             {
1159                 ObjectTypeMapping ocMap = map as ObjectTypeMapping;
1160                 if (ocMap != null)
1161                 {
1162                     edmSpaceType = (T)ocMap.EdmType;
1163                 }
1164             }
1165
1166             return edmSpaceType != null;
1167         }
1168
1169         ///// <summary>
1170         ///// Returns the update or query view for an Extent as a
1171         ///// command tree. For a given Extent, MetadataWorkspace will
1172         ///// have either a Query view or an Update view but not both.
1173         ///// </summary>
1174         ///// <param name="extent"></param>
1175         ///// <returns></returns>
1176         internal DbQueryCommandTree GetCqtView(EntitySetBase extent)
1177         {
1178             return GetGeneratedView(extent).GetCommandTree();
1179         }
1180
1181         /// <summary>
1182         /// Returns generated update or query view for the given extent.
1183         /// </summary>
1184         internal GeneratedView GetGeneratedView(EntitySetBase extent)
1185         {
1186             ItemCollection collection = GetItemCollection(DataSpace.CSSpace, true);
1187             return ((StorageMappingItemCollection)collection).GetGeneratedView(extent, this);
1188         }
1189
1190         /// <summary>
1191         /// Returns a TypeOf/TypeOfOnly Query for a given Extent and Type as a command tree.
1192         /// </summary>
1193         /// <param name="extent"></param>
1194         /// <returns></returns>
1195         internal bool TryGetGeneratedViewOfType(EntitySetBase extent, EntityTypeBase type, bool includeSubtypes, out GeneratedView generatedView)
1196         {
1197             ItemCollection collection = GetItemCollection(DataSpace.CSSpace, true);
1198             return ((StorageMappingItemCollection)collection).TryGetGeneratedViewOfType(this, extent, type, includeSubtypes, out generatedView);
1199         }
1200
1201         /// <summary>
1202         /// Returns generated function definition for the given function.
1203         /// Guarantees type match of declaration and generated parameters.
1204         /// Guarantees return type match.
1205         /// Throws internal error for functions without definition.
1206         /// Passes thru exception occured during definition generation.
1207         /// </summary>
1208         internal DbLambda GetGeneratedFunctionDefinition(EdmFunction function)
1209         {
1210             ItemCollection collection = GetItemCollection(DataSpace.CSpace, true);
1211             return ((EdmItemCollection)collection).GetGeneratedFunctionDefinition(function);
1212         }
1213
1214         /// <summary>
1215         /// Determines if a target function exists for the given function import.
1216         /// </summary>
1217         /// <param name="functionImport">Function import (function declared in a model entity container)</param>
1218         /// <param name="targetFunctionMapping">Function target mapping (function to which the import is mapped in the target store)</param>
1219         /// <returns>true if a mapped target function exists; false otherwise</returns>
1220         internal bool TryGetFunctionImportMapping(EdmFunction functionImport, out FunctionImportMapping targetFunctionMapping)
1221         {
1222             Debug.Assert(null != functionImport);
1223             ReadOnlyCollection<StorageEntityContainerMapping> entityContainerMaps = this.GetItems<StorageEntityContainerMapping>(DataSpace.CSSpace);
1224             foreach (StorageEntityContainerMapping containerMapping in entityContainerMaps)
1225             {
1226                 if (containerMapping.TryGetFunctionImportMapping(functionImport, out targetFunctionMapping))
1227                 {
1228                     return true;
1229                 }
1230             }
1231             targetFunctionMapping = null;
1232             return false;
1233         }
1234
1235         /// <summary>
1236         /// Returns the view loader associated with this workspace,
1237         /// creating a loader if non exists. The loader includes
1238         /// context information used by the update pipeline when
1239         /// processing changes to C-space extents.
1240         /// </summary>
1241         /// <returns></returns>
1242         internal ViewLoader GetUpdateViewLoader()
1243         {
1244             if (_itemsCSSpace != null)
1245             {
1246                 return _itemsCSSpace.GetUpdateViewLoader();
1247             }
1248             return null;
1249         }
1250
1251
1252         /// <summary>
1253         /// Takes in a Edm space type usage and converts into an
1254         /// equivalent O space type usage
1255         /// </summary>
1256         /// <param name="edmSpaceTypeUsage"></param>
1257         /// <returns></returns>
1258         internal TypeUsage GetOSpaceTypeUsage(TypeUsage edmSpaceTypeUsage)
1259         {
1260             EntityUtil.CheckArgumentNull(edmSpaceTypeUsage, "edmSpaceTypeUsage");
1261             Debug.Assert(edmSpaceTypeUsage.EdmType != null, "The TypeUsage object does not have an EDMType.");
1262
1263             EdmType clrType = null;
1264             if (Helper.IsPrimitiveType(edmSpaceTypeUsage.EdmType))
1265             {
1266                 ItemCollection collection = GetItemCollection(DataSpace.OSpace, true);
1267                 clrType = collection.GetMappedPrimitiveType(((PrimitiveType)edmSpaceTypeUsage.EdmType).PrimitiveTypeKind);
1268             }
1269             else
1270             {
1271                 // Check and throw if the OC space doesn't exist
1272                 ItemCollection collection = GetItemCollection(DataSpace.OCSpace, true);
1273
1274                 // Get the OC map
1275                 Map map = ((DefaultObjectMappingItemCollection)collection).GetMap(edmSpaceTypeUsage.EdmType);
1276                 clrType = ((ObjectTypeMapping)map).ClrType;
1277             }
1278
1279             Debug.Assert(!Helper.IsPrimitiveType(clrType) || 
1280                 object.ReferenceEquals(ClrProviderManifest.Instance.GetFacetDescriptions(clrType),
1281                                                 EdmProviderManifest.Instance.GetFacetDescriptions(clrType.BaseType)), 
1282                                                 "these are no longer equal so we can't just use the same set of facets for the new type usage");
1283             
1284             // Transfer the facet values
1285             TypeUsage result = TypeUsage.Create(clrType, edmSpaceTypeUsage.Facets);
1286
1287             return result;
1288         }
1289
1290         /// <summary>
1291         /// Returns true if the item collection for the given space has already been registered else returns false
1292         /// </summary>
1293         /// <param name="dataSpace"></param>
1294         /// <returns></returns>
1295         internal bool IsItemCollectionAlreadyRegistered(DataSpace dataSpace)
1296         {
1297             ItemCollection itemCollection;
1298             return TryGetItemCollection(dataSpace, out itemCollection);
1299         }
1300
1301         /// <summary>
1302         /// Requires: C, S and CS are registered in this and other
1303         /// Determines whether C, S and CS are equivalent. Useful in determining whether a DbCommandTree
1304         /// is usable within a particular entity connection.
1305         /// </summary>
1306         /// <param name="other">Other workspace.</param>
1307         /// <returns>true is C, S and CS collections are equivalent</returns>
1308         internal bool IsMetadataWorkspaceCSCompatible(MetadataWorkspace other)
1309         {
1310             Debug.Assert(this.IsItemCollectionAlreadyRegistered(DataSpace.CSSpace) &&
1311                 other.IsItemCollectionAlreadyRegistered(DataSpace.CSSpace),
1312                 "requires: C, S and CS are registered in this and other");
1313
1314             bool result = this._itemsCSSpace.MetadataEquals(other._itemsCSSpace);
1315
1316             Debug.Assert(!result ||
1317                 (this._itemsCSpace.MetadataEquals(other._itemsCSpace) && this._itemsSSpace.MetadataEquals(other._itemsSSpace)),
1318                 "constraint: this.CS == other.CS --> this.S == other.S && this.C == other.C");
1319             
1320             return result;
1321         }
1322
1323         /// <summary>
1324         /// Clear all the metadata cache entries
1325         /// </summary>
1326         public static void ClearCache()
1327         {
1328             MetadataCache.Clear();
1329             ObjectItemCollection.ViewGenerationAssemblies.Clear();
1330             using (LockedAssemblyCache cache = AssemblyCache.AquireLockedAssemblyCache())
1331             {
1332                 cache.Clear();
1333             }
1334         }
1335
1336         /// <summary>
1337         /// Creates a new Metadata workspace sharing the (currently defined) item collections
1338         /// and tokens for caching purposes.
1339         /// </summary>
1340         /// <returns></returns>
1341         internal MetadataWorkspace ShallowCopy()
1342         {
1343             MetadataWorkspace copy = (MetadataWorkspace)MemberwiseClone();
1344             if (null != copy._cacheTokens) {
1345                 copy._cacheTokens = new List<Object>(copy._cacheTokens);
1346             }
1347             return copy;
1348         }
1349
1350         /// <summary>
1351         /// Returns the canonical Model TypeUsage for a given PrimitiveTypeKind
1352         /// </summary>
1353         /// <param name="primitiveTypeKind">PrimitiveTypeKind for which a canonical TypeUsage is expected</param>
1354         /// <returns>a canonical model TypeUsage</returns>
1355         internal TypeUsage GetCanonicalModelTypeUsage(PrimitiveTypeKind primitiveTypeKind)
1356         {
1357             return EdmProviderManifest.Instance.GetCanonicalModelTypeUsage(primitiveTypeKind);
1358         }
1359
1360         /// <summary>
1361         /// Returns the Model PrimitiveType for a given primitiveTypeKind
1362         /// </summary>
1363         /// <param name="primitiveTypeKind">a PrimitiveTypeKind for which a Model PrimitiveType is expected</param>
1364         /// <returns>Model PrimitiveType</returns>
1365         internal PrimitiveType GetModelPrimitiveType(PrimitiveTypeKind primitiveTypeKind)
1366         {
1367             return EdmProviderManifest.Instance.GetPrimitiveType(primitiveTypeKind);
1368         }
1369
1370         // GetRequiredOriginalValueMembers and GetRelevantMembersForUpdate return list of "interesting" members for the given EntitySet/EntityType
1371         // Interesting Members are a subset of the following:
1372         //    0. Key members
1373         //    1. Members with C-Side conditions (complex types can not have C-side condition at present)
1374         //    2. Members participating in association end
1375         //    3. Members with ConcurrencyMode 'Fixed'
1376         //      3.1 Complex Members with any child member having Concurrency mode Fixed
1377         //    4. Members included in Update ModificationFunction with Version='Original' (Original = Not Current)
1378         //      4.1 Complex Members in ModificationFunction if any sub-member is interesting
1379         //    5. Members included in Update ModificationFunction (mutually exclusive with 4 - required for partial update scenarios)
1380         //    6. Foreign keys
1381         //    7. All complex members - partial update scenarios only
1382         /// <summary>
1383         /// Returns members of a given EntitySet/EntityType for which original values are necessary for determining which tables to modify.
1384         /// </summary>
1385         /// <param name="entitySet">An EntitySet belonging to the C-Space</param>
1386         /// <param name="entityType">An EntityType that participates in the given EntitySet</param>
1387         /// <returns>Edm Members for which original Value is required</returns>
1388         /// <remarks>
1389         /// This method returns the following groups of members: 0, 1, 2, 3, 3.1, 4, 4.1. (see group descriptions above). 
1390         /// This method is marked as obsolete since it does not support partial update scenarios as it does not return 
1391         /// members from group 5 and changing it to return these members would be a breaking change.
1392         /// </remarks>
1393         [Obsolete("Use MetadataWorkspace.GetRelevantMembersForUpdate(EntitySetBase, EntityTypeBase, bool) instead")]
1394         public IEnumerable<EdmMember> GetRequiredOriginalValueMembers(EntitySetBase entitySet, EntityTypeBase entityType)
1395         {
1396             return GetInterestingMembers(entitySet, entityType, StorageMappingItemCollection.InterestingMembersKind.RequiredOriginalValueMembers);
1397         }
1398
1399         /// <summary>
1400         /// Returns members of a given EntitySet/EntityType for which original values are needed when modifying an entity.
1401         /// </summary>
1402         /// <param name="entitySet">An EntitySet belonging to the C-Space</param>
1403         /// <param name="entityType">An EntityType that participates in the given EntitySet</param>
1404         /// <param name="partialUpdateSupported">Whether entities may be updated partially.</param>
1405         /// <returns>Edm Members for which original Value is required</returns>
1406         /// <remarks>
1407         /// This method returns the following groups of members:
1408         /// - if <paramref name="partialUpdateSupported"/> is <c>false</c>: 1, 2, 3, 3.1, 4, 4.1, 6 (see group descriptions above)
1409         /// - if <paramref name="partialUpdateSupported"/> is <c>true</c>: 1, 2, 3, 3.1, 5, 6, 7 (see group descriptions above)
1410         /// See DevDiv bugs #124460 and #272992 for more details.
1411         /// </remarks>
1412         public ReadOnlyCollection<EdmMember> GetRelevantMembersForUpdate(EntitySetBase entitySet, EntityTypeBase entityType, bool partialUpdateSupported)
1413         {
1414             return GetInterestingMembers(
1415                 entitySet, 
1416                 entityType, 
1417                 partialUpdateSupported ? 
1418                     StorageMappingItemCollection.InterestingMembersKind.PartialUpdate : 
1419                     StorageMappingItemCollection.InterestingMembersKind.FullUpdate);
1420         }
1421
1422         /// <summary>
1423         /// Return members for <see cref="GetRequiredOriginalValueMembers"/> and <see cref="GetRelevantMembersForUpdate"/> methods.
1424         /// </summary>
1425         /// <param name="entitySet">An EntitySet belonging to the C-Space</param>
1426         /// <param name="entityType">An EntityType that participates in the given EntitySet</param>
1427         /// <param name="interestingMembersKind">Scenario the members should be returned for.</param>
1428         /// <returns>ReadOnlyCollection of interesting members for the requested scenario (<paramref name="interestingMembersKind"/>).</returns>
1429         private ReadOnlyCollection<EdmMember> GetInterestingMembers(EntitySetBase entitySet, EntityTypeBase entityType, StorageMappingItemCollection.InterestingMembersKind interestingMembersKind)
1430         {
1431             EntityUtil.CheckArgumentNull<EntitySetBase>(entitySet, "entitySet");
1432             EntityUtil.CheckArgumentNull<EntityTypeBase>(entityType, "entityType");
1433
1434             Debug.Assert(entitySet.EntityContainer != null);
1435
1436             //Check that EntitySet is from CSpace
1437             if (entitySet.EntityContainer.DataSpace != DataSpace.CSpace)
1438             {
1439                 AssociationSet associationSet = entitySet as AssociationSet;
1440                 if (associationSet != null)
1441                 {
1442                     throw EntityUtil.AssociationSetNotInCSpace(entitySet.Name);
1443                 }
1444                 else
1445                 {
1446                     throw EntityUtil.EntitySetNotInCSpace(entitySet.Name);
1447                 }
1448             }
1449
1450             //Check that entityType belongs to entitySet
1451             if (!entitySet.ElementType.IsAssignableFrom(entityType))
1452             {
1453                 AssociationSet associationSet = entitySet as AssociationSet;
1454                 if (associationSet != null)
1455                 {
1456                     throw EntityUtil.TypeNotInAssociationSet(entitySet.Name, entitySet.ElementType.FullName, entityType.FullName);
1457                 }
1458                 else
1459                 {
1460                     throw EntityUtil.TypeNotInEntitySet(entitySet.Name, entitySet.ElementType.FullName, entityType.FullName);
1461                 }
1462             }
1463
1464             var mappingCollection = (StorageMappingItemCollection)GetItemCollection(DataSpace.CSSpace, true);
1465             return mappingCollection.GetInterestingMembers(entitySet, entityType, interestingMembersKind);
1466         }
1467
1468         #endregion
1469
1470         #region Properties
1471         /// <summary>
1472         /// Returns the QueryCacheManager hosted by this metadata workspace instance
1473         /// </summary>
1474         internal System.Data.Common.QueryCache.QueryCacheManager GetQueryCacheManager()
1475         {
1476             Debug.Assert(null != _itemsSSpace, "_itemsSSpace must not be null");
1477             return _itemsSSpace.QueryCacheManager;
1478         }
1479
1480         internal Guid MetadataWorkspaceId
1481         {
1482             get
1483             {
1484                 if (Guid.Equals(Guid.Empty, _metadataWorkspaceId))
1485                 {
1486                     _metadataWorkspaceId = Guid.NewGuid();
1487                 }
1488                 return _metadataWorkspaceId;
1489             }
1490         }
1491         #endregion
1492     }
1493 }