You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			429 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			429 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //---------------------------------------------------------------------
 | |
| // <copyright file="StoreItemCollection.cs" company="Microsoft">
 | |
| //      Copyright (c) Microsoft Corporation.  All rights reserved.
 | |
| // </copyright>
 | |
| //
 | |
| // @owner       Microsoft
 | |
| // @backupOwner Microsoft
 | |
| //---------------------------------------------------------------------
 | |
| namespace System.Data.Metadata.Edm
 | |
| {
 | |
|     using System.Collections.Generic;
 | |
|     using System.Data.Common;
 | |
|     using System.Data.Common.Utils;
 | |
|     using System.Data.Entity;
 | |
|     using System.Diagnostics;
 | |
|     using System.Linq;
 | |
|     using System.Runtime.Versioning;
 | |
|     using System.Xml;
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Class for representing a collection of items in Store space.
 | |
|     /// </summary>
 | |
|     [CLSCompliant(false)]
 | |
|     public sealed partial class StoreItemCollection : ItemCollection
 | |
|     {
 | |
|         #region Fields
 | |
| 
 | |
|         double _schemaVersion = XmlConstants.UndefinedVersion;
 | |
| 
 | |
|         // Cache for primitive type maps for Edm to provider
 | |
|         private readonly CacheForPrimitiveTypes _primitiveTypeMaps = new CacheForPrimitiveTypes();
 | |
|         private readonly Memoizer<EdmFunction, EdmFunction> _cachedCTypeFunction;
 | |
| 
 | |
|         private readonly DbProviderManifest _providerManifest;
 | |
|         private readonly string _providerManifestToken;
 | |
|         private readonly DbProviderFactory _providerFactory;
 | |
|         
 | |
|         // Storing the query cache manager in the store item collection since all queries are currently bound to the
 | |
|         // store. So storing it in StoreItemCollection makes sense. Also, since query cache requires version and other
 | |
|         // stuff of the provider, we can assume that the connection is always open and we have the store metadata.
 | |
|         // Also we can use the same cache manager both for Entity Client and Object Query, since query cache has
 | |
|         // no reference to any metadata in OSpace. Also we assume that ObjectMaterializer loads the assembly
 | |
|         // before it tries to do object materialization, since we might not have loaded an assembly in another workspace
 | |
|         // where this store item collection is getting reused
 | |
|         private readonly System.Data.Common.QueryCache.QueryCacheManager _queryCacheManager = System.Data.Common.QueryCache.QueryCacheManager.Create();
 | |
|         #endregion
 | |
| 
 | |
|         #region Constructors
 | |
| 
 | |
|         // used by EntityStoreSchemaGenerator to start with an empty (primitive types only) StoreItemCollection and 
 | |
|         // add types discovered from the database
 | |
|         internal StoreItemCollection(DbProviderFactory factory, DbProviderManifest manifest, string providerManifestToken)
 | |
|             : base(DataSpace.SSpace)
 | |
|         {
 | |
|             Debug.Assert(factory != null, "factory is null");
 | |
|             Debug.Assert(manifest != null, "manifest is null");
 | |
| 
 | |
|             _providerFactory = factory;
 | |
|             _providerManifest = manifest;
 | |
|             _providerManifestToken = providerManifestToken;
 | |
|             _cachedCTypeFunction = new Memoizer<EdmFunction, EdmFunction>(ConvertFunctionSignatureToCType, null);
 | |
|             LoadProviderManifest(_providerManifest, true /*checkForSystemNamespace*/);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// constructor that loads the metadata files from the specified xmlReaders, and returns the list of errors
 | |
|         /// encountered during load as the out parameter errors.
 | |
|         /// 
 | |
|         /// Publicly available from System.Data.Entity.Desgin.dll
 | |
|         /// </summary>
 | |
|         /// <param name="xmlReaders">xmlReaders where the CDM schemas are loaded</param>
 | |
|         /// <param name="filePaths">the paths where the files can be found that match the xml readers collection</param>
 | |
|         /// <param name="errors">An out parameter to return the collection of errors encountered while loading</param>
 | |
|         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] // referenced by System.Data.Entity.Design.dll
 | |
|         internal StoreItemCollection(IEnumerable<XmlReader> xmlReaders,
 | |
|                                      System.Collections.ObjectModel.ReadOnlyCollection<string> filePaths,
 | |
|                                      out IList<EdmSchemaError> errors)
 | |
|             : base(DataSpace.SSpace)
 | |
|         {
 | |
|             // we will check the parameters for this internal ctor becuase
 | |
|             // it is pretty much publicly exposed through the MetadataItemCollectionFactory
 | |
|             // in System.Data.Entity.Design
 | |
|             EntityUtil.CheckArgumentNull(xmlReaders, "xmlReaders");
 | |
|             EntityUtil.CheckArgumentContainsNull(ref xmlReaders, "xmlReaders");
 | |
|             EntityUtil.CheckArgumentEmpty(ref xmlReaders, Strings.StoreItemCollectionMustHaveOneArtifact, "xmlReader");
 | |
|             // filePaths is allowed to be null
 | |
| 
 | |
|             errors = this.Init(xmlReaders, filePaths, false,
 | |
|                 out _providerManifest,
 | |
|                 out _providerFactory,
 | |
|                 out _providerManifestToken,
 | |
|                 out _cachedCTypeFunction);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// constructor that loads the metadata files from the specified xmlReaders, and returns the list of errors
 | |
|         /// encountered during load as the out parameter errors.
 | |
|         /// 
 | |
|         /// Publicly available from System.Data.Entity.Desgin.dll
 | |
|         /// </summary>
 | |
|         /// <param name="xmlReaders">xmlReaders where the CDM schemas are loaded</param>
 | |
|         /// <param name="filePaths">the paths where the files can be found that match the xml readers collection</param>
 | |
|         internal StoreItemCollection(IEnumerable<XmlReader> xmlReaders,
 | |
|                                      IEnumerable<string> filePaths)
 | |
|             : base(DataSpace.SSpace)
 | |
|         {
 | |
|             EntityUtil.CheckArgumentNull(filePaths, "filePaths");
 | |
|             EntityUtil.CheckArgumentEmpty(ref xmlReaders, Strings.StoreItemCollectionMustHaveOneArtifact, "xmlReader");
 | |
| 
 | |
|             this.Init(xmlReaders, filePaths, true,
 | |
|                 out _providerManifest,
 | |
|                 out _providerFactory,
 | |
|                 out _providerManifestToken,
 | |
|                 out _cachedCTypeFunction);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Public constructor that loads the metadata files from the specified xmlReaders.
 | |
|         /// Throws when encounter errors.
 | |
|         /// </summary>
 | |
|         /// <param name="xmlReaders">xmlReaders where the CDM schemas are loaded</param>
 | |
|         public StoreItemCollection(IEnumerable<XmlReader> xmlReaders)
 | |
|             : base(DataSpace.SSpace)
 | |
|         {
 | |
|             EntityUtil.CheckArgumentNull(xmlReaders, "xmlReaders");
 | |
|             EntityUtil.CheckArgumentEmpty(ref xmlReaders, Strings.StoreItemCollectionMustHaveOneArtifact, "xmlReader");
 | |
| 
 | |
|             MetadataArtifactLoader composite = MetadataArtifactLoader.CreateCompositeFromXmlReaders(xmlReaders);
 | |
|             this.Init(composite.GetReaders(),
 | |
|                       composite.GetPaths(), true,
 | |
|                 out _providerManifest,
 | |
|                 out _providerFactory,
 | |
|                 out _providerManifestToken,
 | |
|                 out _cachedCTypeFunction);
 | |
| 
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Constructs the new instance of StoreItemCollection
 | |
|         /// with the list of CDM files provided.
 | |
|         /// </summary>
 | |
|         /// <param name="filePaths">paths where the CDM schemas are loaded</param>
 | |
|         /// <exception cref="ArgumentException"> Thrown if path name is not valid</exception>
 | |
|         /// <exception cref="System.ArgumentNullException">thrown if paths argument is null</exception>
 | |
|         /// <exception cref="System.Data.MetadataException">For errors related to invalid schemas.</exception>
 | |
|         [ResourceExposure(ResourceScope.Machine)] //Exposes the file path names which are a Machine resource
 | |
|         [ResourceConsumption(ResourceScope.Machine)] //For MetadataArtifactLoader.CreateCompositeFromFilePaths method call but we do not create the file paths in this method 
 | |
|         public StoreItemCollection(params string[] filePaths)
 | |
|             : base(DataSpace.SSpace)
 | |
|         {
 | |
|             EntityUtil.CheckArgumentNull(filePaths, "filePaths");
 | |
|             IEnumerable<string> enumerableFilePaths = filePaths;
 | |
|             EntityUtil.CheckArgumentEmpty(ref enumerableFilePaths, Strings.StoreItemCollectionMustHaveOneArtifact, "filePaths");
 | |
| 
 | |
|             // Wrap the file paths in instances of the MetadataArtifactLoader class, which provides
 | |
|             // an abstraction and a uniform interface over a diverse set of metadata artifacts.
 | |
|             //
 | |
|             MetadataArtifactLoader composite = null;
 | |
|             List<XmlReader> readers = null;
 | |
|             try
 | |
|             {
 | |
|                 composite = MetadataArtifactLoader.CreateCompositeFromFilePaths(enumerableFilePaths, XmlConstants.SSpaceSchemaExtension);
 | |
|                 readers = composite.CreateReaders(DataSpace.SSpace);
 | |
|                 IEnumerable<XmlReader> ieReaders = readers.AsEnumerable();
 | |
|                 EntityUtil.CheckArgumentEmpty(ref ieReaders, Strings.StoreItemCollectionMustHaveOneArtifact, "filePaths");
 | |
| 
 | |
|                 this.Init(readers, 
 | |
|                           composite.GetPaths(DataSpace.SSpace), true,
 | |
|                     out _providerManifest,
 | |
|                     out _providerFactory,
 | |
|                     out _providerManifestToken,
 | |
|                     out _cachedCTypeFunction);
 | |
|             }
 | |
|             finally
 | |
|             {
 | |
|                 if (readers != null)
 | |
|                 {
 | |
|                     Helper.DisposeXmlReaders(readers);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
| 
 | |
|         
 | |
| 
 | |
|         private IList<EdmSchemaError> Init(IEnumerable<XmlReader> xmlReaders,
 | |
|                                            IEnumerable<string> filePaths, bool throwOnError,
 | |
|                                            out DbProviderManifest providerManifest,
 | |
|                                            out DbProviderFactory providerFactory,
 | |
|                                            out string providerManifestToken,
 | |
|                                            out Memoizer<EdmFunction, EdmFunction> cachedCTypeFunction)
 | |
|         {
 | |
|             EntityUtil.CheckArgumentNull(xmlReaders, "xmlReaders");
 | |
|             // 'filePaths' can be null
 | |
| 
 | |
|             cachedCTypeFunction = new Memoizer<EdmFunction, EdmFunction>(ConvertFunctionSignatureToCType, null);
 | |
| 
 | |
|             Loader loader = new Loader(xmlReaders, filePaths, throwOnError);
 | |
|             providerFactory = loader.ProviderFactory;
 | |
|             providerManifest = loader.ProviderManifest;
 | |
|             providerManifestToken = loader.ProviderManifestToken;
 | |
| 
 | |
|             // load the items into the colleciton
 | |
|             if (!loader.HasNonWarningErrors)
 | |
|             {
 | |
|                 LoadProviderManifest(loader.ProviderManifest, true /* check for system namespace */);
 | |
|                 List<EdmSchemaError> errorList = EdmItemCollection.LoadItems(_providerManifest, loader.Schemas, this);
 | |
|                 foreach (var error in errorList)
 | |
|                 {
 | |
|                     loader.Errors.Add(error);
 | |
|                 }
 | |
|                 
 | |
|                 if (throwOnError && errorList.Count != 0)
 | |
|                     loader.ThrowOnNonWarningErrors();
 | |
|             }
 | |
|             
 | |
|             return loader.Errors;
 | |
|         }
 | |
|                 
 | |
|         #endregion
 | |
| 
 | |
|         #region Properties
 | |
|         /// <summary>
 | |
|         /// Returns the query cache manager
 | |
|         /// </summary>
 | |
|         internal System.Data.Common.QueryCache.QueryCacheManager QueryCacheManager
 | |
|         {
 | |
|             get { return _queryCacheManager; }
 | |
|         }
 | |
| 
 | |
|         internal DbProviderFactory StoreProviderFactory
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _providerFactory;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal DbProviderManifest StoreProviderManifest
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _providerManifest;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal string StoreProviderManifestToken
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _providerManifestToken;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Version of this StoreItemCollection represents.
 | |
|         /// </summary>
 | |
|         public Double StoreSchemaVersion
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _schemaVersion;
 | |
|             }
 | |
|             internal set
 | |
|             {
 | |
|                 _schemaVersion = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region Methods
 | |
|         /// <summary>
 | |
|         /// Get the list of primitive types for the given space
 | |
|         /// </summary>
 | |
|         /// <returns></returns>
 | |
|         public System.Collections.ObjectModel.ReadOnlyCollection<PrimitiveType> GetPrimitiveTypes()
 | |
|         {
 | |
|             return _primitiveTypeMaps.GetTypes();
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Given the canonical primitive type, get the mapping primitive type in the given dataspace
 | |
|         /// </summary>
 | |
|         /// <param name="primitiveTypeKind">canonical primitive type</param>
 | |
|         /// <returns>The mapped scalar type</returns>
 | |
|         internal override PrimitiveType GetMappedPrimitiveType(PrimitiveTypeKind primitiveTypeKind)
 | |
|         {
 | |
|             PrimitiveType type = null;
 | |
|             _primitiveTypeMaps.TryGetType(primitiveTypeKind, null, out type);
 | |
|             return type;
 | |
|         }
 | |
|                
 | |
|         /// <summary>
 | |
|         /// checks if the schemaKey refers to the provider manifest schema key 
 | |
|         /// and if true, loads the provider manifest
 | |
|         /// </summary>
 | |
|         /// <param name="connection">The connection where the store manifest is loaded from</param>
 | |
|         /// <param name="checkForSystemNamespace">Check for System namespace</param>
 | |
|         /// <returns>The provider manifest object that was loaded</returns>
 | |
|         private void LoadProviderManifest(DbProviderManifest storeManifest,
 | |
|                                                       bool checkForSystemNamespace)
 | |
|         {
 | |
| 
 | |
|             foreach (PrimitiveType primitiveType in storeManifest.GetStoreTypes())
 | |
|             {
 | |
|                 //Add it to the collection and the primitive type maps
 | |
|                 this.AddInternal(primitiveType);
 | |
|                 _primitiveTypeMaps.Add(primitiveType);
 | |
|             }
 | |
| 
 | |
|             foreach (EdmFunction function in storeManifest.GetStoreFunctions())
 | |
|             {
 | |
|                 AddInternal(function);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Get all the overloads of the function with the given name, this method is used for internal perspective
 | |
|         /// </summary>
 | |
|         /// <param name="functionName">The full name of the function</param>
 | |
|         /// <param name="ignoreCase">true for case-insensitive lookup</param>
 | |
|         /// <returns>A collection of all the functions with the given name in the given data space</returns>
 | |
|         /// <exception cref="System.ArgumentNullException">Thrown if functionaName argument passed in is null</exception>
 | |
|         internal System.Collections.ObjectModel.ReadOnlyCollection<EdmFunction> GetCTypeFunctions(string functionName, bool ignoreCase)
 | |
|         {
 | |
|             System.Collections.ObjectModel.ReadOnlyCollection<EdmFunction> functionOverloads;
 | |
| 
 | |
|             if (this.FunctionLookUpTable.TryGetValue(functionName, out functionOverloads))
 | |
|             {
 | |
|                 functionOverloads = ConvertToCTypeFunctions(functionOverloads);
 | |
|                 if (ignoreCase)
 | |
|                 {
 | |
|                     return functionOverloads;
 | |
|                 }
 | |
| 
 | |
|                 return GetCaseSensitiveFunctions(functionOverloads, functionName);
 | |
|             }
 | |
| 
 | |
|             return Helper.EmptyEdmFunctionReadOnlyCollection;
 | |
|         }
 | |
| 
 | |
|         private System.Collections.ObjectModel.ReadOnlyCollection<EdmFunction> ConvertToCTypeFunctions(
 | |
|             System.Collections.ObjectModel.ReadOnlyCollection<EdmFunction> functionOverloads)
 | |
|         {
 | |
|             List<EdmFunction> cTypeFunctions = new List<EdmFunction>();
 | |
|             foreach (var sTypeFunction in functionOverloads)
 | |
|             {
 | |
|                 cTypeFunctions.Add(ConvertToCTypeFunction(sTypeFunction));
 | |
|             }
 | |
|             return cTypeFunctions.AsReadOnly();
 | |
|         }
 | |
| 
 | |
|         internal EdmFunction ConvertToCTypeFunction(EdmFunction sTypeFunction)
 | |
|         {
 | |
|             return this._cachedCTypeFunction.Evaluate(sTypeFunction);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Convert the S type function parameters and returnType to C types.
 | |
|         /// </summary>
 | |
|         private EdmFunction ConvertFunctionSignatureToCType(EdmFunction sTypeFunction)
 | |
|         {
 | |
|             Debug.Assert(sTypeFunction.DataSpace == Edm.DataSpace.SSpace, "sTypeFunction.DataSpace == Edm.DataSpace.SSpace");
 | |
| 
 | |
|             if (sTypeFunction.IsFromProviderManifest)
 | |
|             {
 | |
|                 return sTypeFunction;
 | |
|             }
 | |
|             
 | |
|             FunctionParameter returnParameter = null;
 | |
|             if (sTypeFunction.ReturnParameter != null)
 | |
|             {
 | |
|                 TypeUsage edmTypeUsageReturnParameter =
 | |
|                     MetadataHelper.ConvertStoreTypeUsageToEdmTypeUsage(sTypeFunction.ReturnParameter.TypeUsage);
 | |
| 
 | |
|                 returnParameter =
 | |
|                     new FunctionParameter(
 | |
|                         sTypeFunction.ReturnParameter.Name,
 | |
|                         edmTypeUsageReturnParameter,
 | |
|                         sTypeFunction.ReturnParameter.GetParameterMode());
 | |
|             }
 | |
| 
 | |
|             List<FunctionParameter> parameters = new List<FunctionParameter>();
 | |
|             if (sTypeFunction.Parameters.Count > 0)
 | |
|             {
 | |
|                 
 | |
|                 foreach (var parameter in sTypeFunction.Parameters)
 | |
|                 {
 | |
|                     TypeUsage edmTypeUsage = MetadataHelper.ConvertStoreTypeUsageToEdmTypeUsage(parameter.TypeUsage);
 | |
| 
 | |
|                     FunctionParameter edmTypeParameter = new FunctionParameter(parameter.Name, edmTypeUsage, parameter.GetParameterMode());
 | |
|                     parameters.Add(edmTypeParameter);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             FunctionParameter[] returnParameters = 
 | |
|                 returnParameter == null ? new FunctionParameter[0] : new FunctionParameter[] { returnParameter };
 | |
|             EdmFunction edmFunction = new EdmFunction(sTypeFunction.Name, 
 | |
|                 sTypeFunction.NamespaceName,
 | |
|                 DataSpace.CSpace,
 | |
|                 new EdmFunctionPayload
 | |
|                 {
 | |
|                     Schema = sTypeFunction.Schema,
 | |
|                     StoreFunctionName = sTypeFunction.StoreFunctionNameAttribute,
 | |
|                     CommandText = sTypeFunction.CommandTextAttribute,
 | |
|                     IsAggregate = sTypeFunction.AggregateAttribute,
 | |
|                     IsBuiltIn = sTypeFunction.BuiltInAttribute,
 | |
|                     IsNiladic = sTypeFunction.NiladicFunctionAttribute,
 | |
|                     IsComposable = sTypeFunction.IsComposableAttribute,
 | |
|                     IsFromProviderManifest = sTypeFunction.IsFromProviderManifest,
 | |
|                     IsCachedStoreFunction = true,
 | |
|                     IsFunctionImport = sTypeFunction.IsFunctionImport,
 | |
|                     ReturnParameters = returnParameters,
 | |
|                     Parameters = parameters.ToArray(),
 | |
|                     ParameterTypeSemantics = sTypeFunction.ParameterTypeSemanticsAttribute,
 | |
|                 });
 | |
| 
 | |
|             edmFunction.SetReadOnly();
 | |
| 
 | |
|             return edmFunction;
 | |
|         }
 | |
| 
 | |
|     }//---- ItemCollection
 | |
| 
 | |
| }//---- 
 |