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> MetadataWorkspace()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 MetadataWorkspace(IEnumerable<string> paths, IEnumerable<Assembly> assembliesToConsider)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 CreateMetadataWorkspaceWithResolver(IEnumerable<string> paths, Func<IEnumerable<Assembly>> wildcardAssemblies, Func<AssemblyName, Assembly> resolveReference)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> CreateEntitySqlParser()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> CreateQueryCommandTree(DbExpression query)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)] GetItemCollection(DataSpace dataSpace)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)] RegisterItemCollection(ItemCollection collection)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> CheckAndSetItemCollectionVersionInWorkSpace(ItemCollection itemCollectionToRegister)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> AddMetadataEntryToken(object token)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> LoadFromAssembly(Assembly assembly)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> LoadFromAssembly(Assembly assembly, Action<string> logLoadMessage)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 ExplicitLoadFromAssembly(Assembly assembly, ObjectItemCollection collection, Action<string> logLoadMessage)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 ImplicitLoadFromAssembly(Assembly assembly, ObjectItemCollection collection)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> ImplicitLoadAssemblyForType(Type type, Assembly callingAssembly)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> ImplicitLoadFromEntityType(EntityType type, Assembly callingAssembly)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> GetType(string name, string namespaceName, DataSpace dataSpace)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> TryGetType(string name, string namespaceName, DataSpace dataSpace, out EdmType type)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> GetType(string name, string namespaceName, bool ignoreCase, DataSpace dataSpace)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> TryGetType(string name, string namespaceName, bool ignoreCase, DataSpace dataSpace, out EdmType type)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> GetEntityContainer(string name, DataSpace dataSpace)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> TryGetEntityContainer(string name, DataSpace dataSpace, out EntityContainer entityContainer)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> GetEntityContainer(string name, bool ignoreCase, DataSpace dataSpace)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> TryGetEntityContainer(string name, bool ignoreCase, DataSpace dataSpace, out EntityContainer entityContainer)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> GetFunctions(string name, string namespaceName, DataSpace dataSpace)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> GetFunctions(string name, string namespaceName, DataSpace dataSpace, bool ignoreCase)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> TryGetFunction(string name, string namespaceName, TypeUsage[] parameterTypes, bool ignoreCase, DataSpace dataSpace, out EdmFunction function)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> GetPrimitiveTypes(DataSpace dataSpace)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> GetItems(DataSpace dataSpace)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> GetMappedPrimitiveType(PrimitiveTypeKind primitiveTypeKind, DataSpace dataSpace)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> TryGetMap(string typeIdentity, DataSpace typeSpace, bool ignoreCase, DataSpace mappingSpace, out Map map)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> GetMap(string identity, DataSpace typeSpace, DataSpace dataSpace)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> GetMap(GlobalItem item, DataSpace dataSpace)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> TryGetMap(GlobalItem item, DataSpace dataSpace, out Map map)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 RegisterDefaultObjectMappingItemCollection()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)] TryGetItemCollection(DataSpace dataSpace, out ItemCollection collection)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> GetItemCollection(DataSpace dataSpace, bool required)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")] GetObjectSpaceType(StructuralType edmSpaceType)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")] TryGetObjectSpaceType(StructuralType edmSpaceType, out StructuralType objectSpaceType)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")] GetObjectSpaceType(EnumType edmSpaceType)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")] TryGetObjectSpaceType(EnumType edmSpaceType, out EnumType objectSpaceType)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")] GetEdmSpaceType(StructuralType objectSpaceType)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")] TryGetEdmSpaceType(StructuralType objectSpaceType, out StructuralType edmSpaceType)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")] GetEdmSpaceType(EnumType objectSpaceType)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")] TryGetEdmSpaceType(EnumType objectSpaceType, out EnumType edmSpaceType)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> GetCqtView(EntitySetBase extent)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> GetGeneratedView(EntitySetBase extent)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> TryGetGeneratedViewOfType(EntitySetBase extent, EntityTypeBase type, bool includeSubtypes, out GeneratedView generatedView)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> GetGeneratedFunctionDefinition(EdmFunction function)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> TryGetFunctionImportMapping(EdmFunction functionImport, out FunctionImportMapping targetFunctionMapping)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> GetUpdateViewLoader()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> GetOSpaceTypeUsage(TypeUsage edmSpaceTypeUsage)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> IsItemCollectionAlreadyRegistered(DataSpace dataSpace)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> IsMetadataWorkspaceCSCompatible(MetadataWorkspace other)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> ClearCache()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> ShallowCopy()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> GetCanonicalModelTypeUsage(PrimitiveTypeKind primitiveTypeKind)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> GetModelPrimitiveType(PrimitiveTypeKind primitiveTypeKind)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")] GetRequiredOriginalValueMembers(EntitySetBase entitySet, EntityTypeBase entityType)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> GetRelevantMembersForUpdate(EntitySetBase entitySet, EntityTypeBase entityType, bool partialUpdateSupported)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> GetInterestingMembers(EntitySetBase entitySet, EntityTypeBase entityType, StorageMappingItemCollection.InterestingMembersKind interestingMembersKind)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> GetQueryCacheManager()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 } 1494