EdmItemCollection.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Metadata / EdmItemCollection.cs / 1305376 / EdmItemCollection.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 
using System;
using System.Collections.Generic; 
using System.Collections.ObjectModel;
using System.Data.Common.Utils;
using System.Data.EntityModel;
using System.Data.EntityModel.SchemaObjectModel; 
using System.Data.Metadata.Edm;
using System.Diagnostics; 
using System.Text; 
using System.Xml.Serialization;
using System.Xml; 
using System.Xml.Schema;
using System.IO;
using System.Data.Common;
using System.Data.Common.CommandTrees; 
using System.Data.Common.QueryCache;
using System.Data.Objects.ELinq; 
using System.Data.Entity; 
using System.Threading;
using System.Runtime.Versioning; 
using System.Reflection;

namespace System.Data.Metadata.Edm
{ 
    /// 
    /// Class for representing a collection of items in Edm space. 
    ///  
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")]
    [CLSCompliant(false)] 
    public sealed class EdmItemCollection : ItemCollection
    {
        #region Constructors
        ///  
        /// constructor that loads the metadata files from the specified xmlReaders, and returns the list of errors
        /// encountered during load as the out parameter errors. 
        ///  
        /// xmlReaders where the CDM schemas are loaded
        /// Paths (URIs)to the CSDL files or resources 
        /// An out parameter to return the collection of errors encountered while loading
        // referenced by System.Data.Entity.Design.dll
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        internal EdmItemCollection(IEnumerable xmlReaders, 
                                   System.Collections.ObjectModel.ReadOnlyCollection filePaths,
                                   out IList errors) 
            : base(DataSpace.CSpace) 
        {
            // we will check the parameters for this internal ctor becuase 
            // it is pretty much publicly exposed through the MetadataItemCollectionFactory
            // in System.Data.Entity.Design
            //
            // we are intentionally not checking for an empty enumerable 
            EntityUtil.CheckArgumentNull(xmlReaders, "xmlReaders");
            EntityUtil.CheckArgumentContainsNull(ref xmlReaders, "xmlReaders"); 
            // filePaths is allowed to be null 

            errors = this.Init(xmlReaders, filePaths, false /*throwOnErrors*/); 
        }

        /// 
        /// constructor that loads the metadata files from the specified schemas 
        /// 
        /// list of schemas to be loaded into the ItemCollection 
        // referenced by System.Data.Entity.Design.dll 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        internal EdmItemCollection(IList schemas) 
            : base(DataSpace.CSpace)
        {
            this.Init();
            LoadItems(MetadataItem.EdmProviderManifest, schemas, this); 
        }
 
        ///  
        /// constructor that loads the metadata files from the specified xmlReaders
        ///  
        /// xmlReaders where the CDM schemas are loaded
        /// Paths (URIs)to the CSDL files or resources
        internal EdmItemCollection(IEnumerable xmlReaders,
                                   IEnumerable filePaths) 
            : base(DataSpace.CSpace)
        { 
            this.Init(xmlReaders, filePaths, true /*throwOnErrors*/); 
        }
 
        /// 
        /// Public constructor that loads the metadata files from the specified XmlReaders
        /// 
        /// XmlReader objects where the EDM schemas are loaded 
        public EdmItemCollection(IEnumerable xmlReaders)
            : base(DataSpace.CSpace) 
        { 
            EntityUtil.CheckArgumentNull(xmlReaders, "xmlReaders");
            EntityUtil.CheckArgumentContainsNull(ref xmlReaders, "xmlReaders"); 

            MetadataArtifactLoader composite = MetadataArtifactLoader.CreateCompositeFromXmlReaders(xmlReaders);

            this.Init(composite.GetReaders(), 
                      composite.GetPaths(),
                      true /*throwOnError*/); 
 
        }
 
        /// 
        /// Constructs the new instance of EdmItemCollection
        /// with the list of CDM files provided.
        ///  
        /// paths where the CDM schemas are loaded
        ///  Thrown if path name is not valid 
        /// thrown if paths argument is null 
        /// For errors related to invalid schemas.
        [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 EdmItemCollection(params string[] filePaths)
            : base(DataSpace.CSpace)
        { 
            EntityUtil.CheckArgumentNull(filePaths, "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 readers = null;
            try
            { 
                composite = MetadataArtifactLoader.CreateCompositeFromFilePaths(filePaths, XmlConstants.CSpaceSchemaExtension);
                readers = composite.CreateReaders(DataSpace.CSpace); 
                this.Init(readers, 
                          composite.GetPaths(DataSpace.CSpace),
                          true /*throwOnError*/); 
            }
            finally
            {
                if (readers != null) 
                {
                    Helper.DisposeXmlReaders(readers); 
                } 
            }
        } 


        // the most basic initialization
        private void Init() 
        {
            // Load the EDM primitive types 
            LoadEdmPrimitiveTypesAndFunctions(); 
        }
 

        /// 
        /// Public constructor that loads the metadata files from the specified XmlReaders, and
        /// returns the list of errors encountered during load as the out parameter 'errors'. 
        /// 
        /// XmlReader objects where the EDM schemas are loaded 
        /// Paths (URIs) to the CSDL files or resources 
        /// A flag to indicate whether to throw if LoadItems returns errors
        private IList Init(IEnumerable xmlReaders, 
                                           IEnumerable filePaths,
                                           bool throwOnError)
        {
            EntityUtil.CheckArgumentNull(xmlReaders, "xmlReaders"); 

            // do the basic initialization 
            Init(); 

            IList errors = LoadItems(xmlReaders, filePaths, SchemaDataModelOption.EntityDataModel, 
                MetadataItem.EdmProviderManifest, this, throwOnError);

            return errors;
        } 

        #endregion 
 
        #region Fields
 
        // Cache for primitive type maps for Edm to provider
        private CacheForPrimitiveTypes _primitiveTypeMaps = new CacheForPrimitiveTypes();

        private Double _edmVersion = XmlConstants.UndefinedVersion; 
        /// 
        /// Gets canonical versions of InitializerMetadata instances. This avoids repeatedly 
        /// compiling delegates for materialization. 
        /// 
        private Memoizer _getCanonicalInitializerMetadataMemoizer; 

        /// 
        /// Manages user defined function definitions.
        ///  
        private Memoizer _getGeneratedFunctionDefinitionsMemoizer;
 
        private OcAssemblyCache _conventionalOcCache = new OcAssemblyCache(); 

        #endregion 

        #region Properties
        /// 
        /// Version of the EDM that this ItemCollection represents. 
        /// The Edm Version of the ItemCollection will be the max version
        /// of the schemas that the item collection is constructed of. 
        ///  
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")]
        public Double EdmVersion 
        {
            get { return _edmVersion; }
            internal set { _edmVersion = value; }
        } 

        ///  
        /// conventional oc mapping cache, the locking mechanism is provided by ----semblyCache 
        /// 
        internal OcAssemblyCache ConventionalOcCache 
        {
            get { return _conventionalOcCache; }
        }
        #endregion 

        #region Methods 
        ///  
        /// Given an InitializerMetadata instance, returns the canonical version of that instance.
        /// This allows us to avoid compiling materialization delegates repeatedly for the same 
        /// pattern.
        /// 
        internal InitializerMetadata GetCanonicalInitializerMetadata(InitializerMetadata metadata)
        { 
            if (null == _getCanonicalInitializerMetadataMemoizer)
            { 
                // We memoize the identity function because the first evaluation of the function establishes 
                // the canonical 'reference' for the initializer metadata with a particular 'value'.
                Interlocked.CompareExchange(ref _getCanonicalInitializerMetadataMemoizer, new Memoizer( 
                    m => m, EqualityComparer.Default), null);
            }

            // check if an equivalent has already been registered 
            InitializerMetadata canonical = _getCanonicalInitializerMetadataMemoizer.Evaluate(metadata);
            return canonical; 
        } 

        internal static bool IsSystemNamespace(DbProviderManifest manifest, string namespaceName) 
        {
            if (manifest == MetadataItem.EdmProviderManifest)
            {
                return (namespaceName == EdmConstants.TransientNamespace || 
                        namespaceName == EdmConstants.EdmNamespace ||
                        namespaceName == EdmConstants.ClrPrimitiveTypeNamespace); 
            } 
            else
            { 
                return (namespaceName == EdmConstants.TransientNamespace ||
                        namespaceName == EdmConstants.EdmNamespace ||
                        namespaceName == EdmConstants.ClrPrimitiveTypeNamespace ||
                        (manifest != null && namespaceName == manifest.NamespaceName)); 
            }
        } 
 
        /// 
        /// Load stuff from xml readers - this now includes XmlReader instances created over embedded 
        /// resources. See the remarks section below for some useful information.
        /// 
        /// A list of XmlReader instances
        /// whether this is a entity data model or provider data model 
        /// provider manifest from which the primitive type definition comes from
        /// item collection to add the item after loading 
        /// Indicates whether the method should bother with the file paths; see remarks below 
        /// 
        /// In order to accommodate XmlReaders over artifacts embedded as resources in assemblies, the 
        /// notion of a filepath had to be abstracted into a URI. In reality, however, a res:// URI that
        /// points to an embedded resource does not constitute a valid URI (i.e., one that can be parsed
        /// by the System.Uri class in the .NET framework). In such cases, we need to supply a list of
        /// "filepaths" (which includes res:// URIs), instead of having this method create the collection. 
        /// This distinction is made by setting the 'computeFilePaths' flags appropriately.
        ///  
        internal static IList LoadItems(IEnumerable xmlReaders, 
                                                       IEnumerable sourceFilePaths,
                                                       SchemaDataModelOption dataModelOption, 
                                                       DbProviderManifest providerManifest,
                                                       ItemCollection itemCollection,
                                                       bool throwOnError)
        { 
            IList schemaCollection = null;
 
            // Parse and validate all the schemas - since we support using now, 
            // we need to parse them as a group
            var errorCollection = SchemaManager.ParseAndValidate(xmlReaders, sourceFilePaths, 
                dataModelOption, providerManifest, out schemaCollection);

            // Try to initialize the metadata if there are no errors
            if (MetadataHelper.CheckIfAllErrorsAreWarnings(errorCollection)) 
            {
                List errors = LoadItems(providerManifest, schemaCollection, itemCollection); 
                foreach (var error in errors) 
                {
                    errorCollection.Add(error); 
                }
            }
            if (!MetadataHelper.CheckIfAllErrorsAreWarnings(errorCollection) && throwOnError)
            { 
                //Future Enhancement: if there is an error, we throw exception with error and warnings.
                //Otherwise the user has no clue to know about warnings. 
                throw EntityUtil.InvalidSchemaEncountered(Helper.CombineErrorMessage(errorCollection)); 
            }
            return errorCollection; 
        }

        internal static List LoadItems(DbProviderManifest manifest, IList somSchemas,
            ItemCollection itemCollection) 
        {
 
            List errors = new List(); 
            // Convert the schema, if model schema, then we use the EDM provider manifest, otherwise use the
            // store provider manifest 
            IEnumerable newGlobalItems = LoadSomSchema(somSchemas, manifest, itemCollection);
            List tempCTypeFunctionIdentity = new List();

            // No errors, so go ahead and add the types and make them readonly 
            foreach (GlobalItem globalItem in newGlobalItems)
            { 
                // If multiple function parameter and return types expressed in SSpace map to the same 
                // CSpace type (e.g., SqlServer.decimal and SqlServer.numeric both map to Edm.Decimal),
                // we need to guard against attempts to insert duplicate functions into the collection. 
                //
                if (globalItem.BuiltInTypeKind == BuiltInTypeKind.EdmFunction && globalItem.DataSpace == DataSpace.SSpace)
                {
                    EdmFunction function = (EdmFunction)globalItem; 

                    StringBuilder sb = new StringBuilder(); 
                    EdmFunction.BuildIdentity( 
                        sb,
                        function.FullName, 
                        function.Parameters,
                        // convert function parameters to C-side types
                        (param) => MetadataHelper.ConvertStoreTypeUsageToEdmTypeUsage(param.TypeUsage),
                        (param) => param.Mode); 
                    string cTypeFunctionIdentity = sb.ToString();
 
                    // Validate identity 
                    if (tempCTypeFunctionIdentity.Contains(cTypeFunctionIdentity))
                    { 

                        errors.Add(
                            new EdmSchemaError(
                                Strings.DuplicatedFunctionoverloads(function.FullName, cTypeFunctionIdentity.Substring(function.FullName.Length)).Trim()/*parameters*/, 
                                (int)ErrorCode.DuplicatedFunctionoverloads,
                                EdmSchemaErrorSeverity.Error)); 
                        continue; 
                    }
 
                    tempCTypeFunctionIdentity.Add(cTypeFunctionIdentity);
                }
                globalItem.SetReadOnly();
                itemCollection.AddInternal(globalItem); 
            }
            return errors; 
        } 

        ///  
        /// Load metadata from a SOM schema directly
        /// 
        /// The SOM schema to load from
        /// The provider manifest used for loading the type 
        /// item collection in which primitive types are present
        /// The newly created items 
        internal static IEnumerable LoadSomSchema(IList somSchemas, 
                                                              DbProviderManifest providerManifest,
                                                              ItemCollection itemCollection) 
        {
            IEnumerable newGlobalItems = Converter.ConvertSchema(somSchemas,
                providerManifest, itemCollection);
            return newGlobalItems; 
        }
 
        ///  
        /// Get the list of primitive types for the given space
        ///  
        /// 
        public System.Collections.ObjectModel.ReadOnlyCollection GetPrimitiveTypes()
        {
            return _primitiveTypeMaps.GetTypes(); 
        }
 
 
        /// 
        /// Given the canonical primitive type, get the mapping primitive type in the given dataspace 
        /// 
        /// canonical primitive type
        /// The mapped scalar type
        internal override PrimitiveType GetMappedPrimitiveType(PrimitiveTypeKind primitiveTypeKind) 
        {
            PrimitiveType type = null; 
            _primitiveTypeMaps.TryGetType(primitiveTypeKind, null, out type); 
            return type;
        } 

        private void LoadEdmPrimitiveTypesAndFunctions()
        {
            EdmProviderManifest providerManifest = EdmProviderManifest.Instance; 
            System.Collections.ObjectModel.ReadOnlyCollection primitiveTypes = providerManifest.GetStoreTypes();
            for (int i = 0; i < primitiveTypes.Count; i++) 
            { 
                this.AddInternal(primitiveTypes[i]);
                _primitiveTypeMaps.Add(primitiveTypes[i]); 
            }
            System.Collections.ObjectModel.ReadOnlyCollection functions = providerManifest.GetStoreFunctions();
            for (int i = 0; i < functions.Count; i++)
            { 
                this.AddInternal(functions[i]);
            } 
        } 

        ///  
        /// Generates function definition or returns a cached one.
        /// Guarantees type match of declaration and generated parameters.
        /// Guarantees return type match.
        /// Throws internal error for functions without definition. 
        /// Passes thru exceptions occured during definition generation.
        ///  
        internal DbLambda GetGeneratedFunctionDefinition(EdmFunction function) 
        {
            if (null == _getGeneratedFunctionDefinitionsMemoizer) 
            {
                Interlocked.CompareExchange(
                    ref _getGeneratedFunctionDefinitionsMemoizer,
                    new Memoizer(GenerateFunctionDefinition, null), 
                    null);
            } 
 
            return _getGeneratedFunctionDefinitionsMemoizer.Evaluate(function);
        } 

        /// 
        /// Generates function definition or returns a cached one.
        /// Guarantees type match of declaration and generated parameters. 
        /// Guarantees return type match.
        /// Throws internal error for functions without definition. 
        /// Passes thru exceptions occured during definition generation. 
        /// 
        internal DbLambda GenerateFunctionDefinition(EdmFunction function) 
        {
            if (!function.HasUserDefinedBody)
            {
                throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.AttemptToGenerateDefinitionForFunctionWithoutDef, 0, function.FullName); 
            }
 
            DbLambda generatedDefinition; 

            // Generate the body 
            generatedDefinition = Mapping.ViewGeneration.Utils.ExternalCalls.CompileFunctionDefinition(
                function.FullName,
                function.CommandTextAttribute,
                function.Parameters, 
                this);
 
            // Ensure the result type of the generated definition matches the result type of the edm function (the declaration) 
            if (!TypeSemantics.IsStructurallyEqual(function.ReturnParameter.TypeUsage, generatedDefinition.Body.ResultType))
            { 
                throw EntityUtil.FunctionDefinitionResultTypeMismatch(function, generatedDefinition.Body.ResultType);
            }

            Debug.Assert(generatedDefinition != null, "generatedDefinition != null"); 

            return generatedDefinition; 
        } 
        #endregion
    }//---- ItemCollection 

}//----

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK