EdmProviderManifest.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Metadata / Edm / Provider / EdmProviderManifest.cs / 1305376 / EdmProviderManifest.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System.Data.Common; 
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Threading; 

namespace System.Data.Metadata.Edm 
{ 
    internal class EdmProviderManifest : DbProviderManifest
    { 
        /// 
        /// The ConcurrencyMode Facet Name
        /// 
        internal const string ConcurrencyModeFacetName = "ConcurrencyMode"; 
        /// 
        /// The StoreGeneratedPattern Facet Name 
        ///  
        internal const string StoreGeneratedPatternFacetName = "StoreGeneratedPattern";
        private Dictionary> _facetDescriptions; 
        private System.Collections.ObjectModel.ReadOnlyCollection _primitiveTypes;
        private System.Collections.ObjectModel.ReadOnlyCollection _functions;
        private static EdmProviderManifest _instance = new EdmProviderManifest();
        private System.Collections.ObjectModel.ReadOnlyCollection[] _promotionTypes; 
        static TypeUsage[] _canonicalModelTypes;
 
        internal const byte MaximumDecimalPrecision = Byte.MaxValue; 
        internal const byte MaximumDateTimePrecision = Byte.MaxValue;
 
        /// 
        /// A private constructor to prevent other places from instantiating this class
        /// 
        private EdmProviderManifest() 
        {
        } 
 
        /// 
        /// Gets the EDM provider manifest singleton instance 
        /// 
        internal static EdmProviderManifest Instance
        {
            get 
            {
                return _instance; 
            } 
        }
 
        /// 
        /// Returns the namespace used by this provider manifest
        /// 
        public override string NamespaceName 
        {
            get { return EdmConstants.EdmNamespace; } 
        } 

        ///  
        /// Store version hint
        /// 
        internal string Token
        { 
            // we shouldn't throw exception on properties
            get { return String.Empty; } 
        } 

        ///  
        /// Returns the list of all the canonical functions
        /// 
        /// 
        public override System.Collections.ObjectModel.ReadOnlyCollection GetStoreFunctions() 
        {
            InitializeCanonicalFunctions(); 
            return _functions; 
        }
 
        /// 
        /// Returns all the FacetDescriptions for a particular type
        /// 
        /// the type to return FacetDescriptions for. 
        /// The FacetDescriptions for the type given.
        public override System.Collections.ObjectModel.ReadOnlyCollection GetFacetDescriptions(EdmType type) 
        { 
            Debug.Assert(type is PrimitiveType, "EdmProviderManifest.GetFacetDescriptions(): Argument is not a PrimitiveType");
 
            InitializeFacetDescriptions();

            // Some types may not have facets, so just try to get them, if there aren't any, just return an empty list
            System.Collections.ObjectModel.ReadOnlyCollection collection = null; 
            if (_facetDescriptions.TryGetValue(type as PrimitiveType, out collection))
            { 
                return collection; 
            }
            return Helper.EmptyFacetDescriptionEnumerable; 
        }

        /// 
        /// Returns a primitive type from this manifest having the specified primitive type kind 
        /// 
        /// The value specifying the kind of primitive type to return 
        /// A primitive type having the given primitive type kind 
        public PrimitiveType GetPrimitiveType(PrimitiveTypeKind primitiveTypeKind)
        { 
            InitializePrimitiveTypes();
            return _primitiveTypes[(int)primitiveTypeKind];
        }
 
        /// 
        /// Boostrapping all the primitive types for the EDM Provider Manifest 
        ///  
        private void InitializePrimitiveTypes()
        { 
            if (_primitiveTypes != null)
            {
                return;
            } 

            PrimitiveType[] primitiveTypes = new PrimitiveType[EdmConstants.NumPrimitiveTypes]; 
            primitiveTypes[(int)PrimitiveTypeKind.Binary] = new PrimitiveType(); 
            primitiveTypes[(int)PrimitiveTypeKind.Boolean] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.Byte] = new PrimitiveType(); 
            primitiveTypes[(int)PrimitiveTypeKind.DateTime] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.Decimal] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.Double] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.Single] = new PrimitiveType(); 
            primitiveTypes[(int)PrimitiveTypeKind.Guid] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.Int16] = new PrimitiveType(); 
            primitiveTypes[(int)PrimitiveTypeKind.Int32] = new PrimitiveType(); 
            primitiveTypes[(int)PrimitiveTypeKind.Int64] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.SByte] = new PrimitiveType(); 
            primitiveTypes[(int)PrimitiveTypeKind.String] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.Time] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.DateTimeOffset] = new PrimitiveType();
 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Binary], PrimitiveTypeKind.Binary, EdmConstants.Binary, typeof(Byte[]));
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Boolean], PrimitiveTypeKind.Boolean, EdmConstants.Boolean, typeof(Boolean)); 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Byte], PrimitiveTypeKind.Byte, EdmConstants.Byte, typeof(Byte)); 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.DateTime], PrimitiveTypeKind.DateTime, EdmConstants.DateTime, typeof(DateTime));
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Decimal], PrimitiveTypeKind.Decimal, EdmConstants.Decimal, typeof(Decimal)); 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Double], PrimitiveTypeKind.Double, EdmConstants.Double, typeof(Double));
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Single], PrimitiveTypeKind.Single, EdmConstants.Single, typeof(Single));
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Guid], PrimitiveTypeKind.Guid, EdmConstants.Guid, typeof(Guid));
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Int16], PrimitiveTypeKind.Int16, EdmConstants.Int16, typeof(Int16)); 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Int32], PrimitiveTypeKind.Int32, EdmConstants.Int32, typeof(Int32));
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Int64], PrimitiveTypeKind.Int64, EdmConstants.Int64, typeof(Int64)); 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.SByte], PrimitiveTypeKind.SByte, EdmConstants.SByte, typeof(SByte)); 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.String], PrimitiveTypeKind.String, EdmConstants.String, typeof(String));
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Time], PrimitiveTypeKind.Time, EdmConstants.Time, typeof(TimeSpan)); 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.DateTimeOffset], PrimitiveTypeKind.DateTimeOffset, EdmConstants.DateTimeOffset, typeof(DateTimeOffset));

            // Set all primitive types to be readonly
            foreach (PrimitiveType primitiveType in primitiveTypes) 
            {
                primitiveType.ProviderManifest = this; 
                primitiveType.SetReadOnly(); 
            }
 
            System.Collections.ObjectModel.ReadOnlyCollection readOnlyTypes = new System.Collections.ObjectModel.ReadOnlyCollection(primitiveTypes);

            // Set the result to _primitiveTypes at the end
            Interlocked.CompareExchange>(ref _primitiveTypes, readOnlyTypes, null); 
        }
 
        ///  
        /// Initialize all the primitive type with the given primitive type kind and name
        ///  
        /// The primitive type to initialize
        /// Type of the primitive type which is getting initialized
        /// name of the built in type
        /// the CLR Type of that maps to the EDM PrimitiveType 
        private void InitializePrimitiveType(PrimitiveType primitiveType,
                                             PrimitiveTypeKind primitiveTypeKind, 
                                             string name, 
                                             Type clrType)
        { 
            // Only null types are not abstract and they are sealed, all others are abstract and unsealed
            EdmType.Initialize(primitiveType, name,
                               EdmConstants.EdmNamespace,
                               DataSpace.CSpace, 
                               true /* isabstract */,
                               null /* baseType */); 
            PrimitiveType.Initialize(primitiveType, 
                                     primitiveTypeKind,
                                     true, // isDefault 
                                     this);
            Debug.Assert(clrType == primitiveType.ClrEquivalentType, "ClrEquivalentType mismatch");
        }
 
        /// 
        /// Boostrapping all the facet descriptions for the EDM Provider Manifest 
        ///  
        private void InitializeFacetDescriptions()
        { 
            if (_facetDescriptions != null)
            {
                return;
            } 

            // Ensure the primitive types are there 
            InitializePrimitiveTypes(); 

            // Create the dictionary of facet descriptions 
            Dictionary> facetDescriptions = new Dictionary>();

            // String facets
            FacetDescription[] list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.String); 
            PrimitiveType applicableType = _primitiveTypes[(int)PrimitiveTypeKind.String];
            facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); 
 
            // Binary facets
            list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.Binary); 
            applicableType = _primitiveTypes[(int)PrimitiveTypeKind.Binary];
            facetDescriptions.Add(applicableType, Array.AsReadOnly(list));

            // DateTime facets 
            list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.DateTime);
            applicableType = _primitiveTypes[(int)PrimitiveTypeKind.DateTime]; 
            facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); 

            // Time facets 
            list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.Time);
            applicableType = _primitiveTypes[(int)PrimitiveTypeKind.Time];
            facetDescriptions.Add(applicableType, Array.AsReadOnly(list));
 
            // DateTimeOffset facets
            list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.DateTimeOffset); 
            applicableType = _primitiveTypes[(int)PrimitiveTypeKind.DateTimeOffset]; 
            facetDescriptions.Add(applicableType, Array.AsReadOnly(list));
 

            // Decimal facets
            list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.Decimal);
            applicableType = _primitiveTypes[(int)PrimitiveTypeKind.Decimal]; 
            facetDescriptions.Add(applicableType, Array.AsReadOnly(list));
 
            // Set the result to _facetDescriptions at the end 
            Interlocked.CompareExchange>>(ref _facetDescriptions,
                                                                                                         facetDescriptions, 
                                                                                                         null);
        }

        internal static FacetDescription[] GetInitialFacetDescriptions(PrimitiveTypeKind primitiveTypeKind) 
        {
            FacetDescription[] list; 
 
            switch (primitiveTypeKind)
            { 
                case PrimitiveTypeKind.String:
                    {
                        list = new FacetDescription[3];
 
                        list[0] = (new FacetDescription(DbProviderManifest.MaxLengthFacetName,
                                                      MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Int32), 
                                                      0, 
                                                      Int32.MaxValue,
                                                      null)); 
                        list[1] = (new FacetDescription(DbProviderManifest.UnicodeFacetName,
                                                      MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Boolean),
                                                      null,
                                                      null, 
                                                      null));
                        list[2] = (new FacetDescription(DbProviderManifest.FixedLengthFacetName, 
                                                      MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Boolean), 
                                                      null,
                                                      null, 
                                                      null));

                        return list;
                    } 

                case PrimitiveTypeKind.Binary: 
                    { 
                        list = new FacetDescription[2];
 
                        list[0] = (new FacetDescription(DbProviderManifest.MaxLengthFacetName,
                                                      MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Int32),
                                                      0,
                                                      Int32.MaxValue, 
                                                      null));
                        list[1] = (new FacetDescription(DbProviderManifest.FixedLengthFacetName, 
                                                      MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Boolean), 
                                                      null,
                                                      null, 
                                                      null));
                        return list;
                    }
 
                case PrimitiveTypeKind.DateTime:
                    { 
                        list = new FacetDescription[1]; 

                        list[0] = (new FacetDescription(DbProviderManifest.PrecisionFacetName, 
                              MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte),
                              0, EdmProviderManifest.MaximumDateTimePrecision, null));

                        return list; 
                    }
                case PrimitiveTypeKind.Time: 
                    { 
                        list = new FacetDescription[1];
 
                        list[0] = (new FacetDescription(DbProviderManifest.PrecisionFacetName,
                              MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte),
                              0, EdmProviderManifest.MaximumDateTimePrecision, TypeUsage.DefaultDateTimePrecisionFacetValue));
 
                        return list;
                    } 
                case PrimitiveTypeKind.DateTimeOffset: 
                    {
                        list = new FacetDescription[1]; 
                        list[0] = (new FacetDescription(DbProviderManifest.PrecisionFacetName,
                              MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte),
                              0, EdmProviderManifest.MaximumDateTimePrecision, TypeUsage.DefaultDateTimePrecisionFacetValue));
 
                        return list;
                    } 
                case PrimitiveTypeKind.Decimal: 
                    {
                        list = new FacetDescription[2]; 

                        list[0] = (new FacetDescription(DbProviderManifest.PrecisionFacetName,
                                                      MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte),
                                                      1, 
                                                      EdmProviderManifest.MaximumDecimalPrecision,
                                                      null)); 
                        list[1] = (new FacetDescription(DbProviderManifest.ScaleFacetName, 
                                                      MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte),
                                                      0, 
                                                      EdmProviderManifest.MaximumDecimalPrecision,
                                                      null));
                        return list;
                    } 

                default: 
                    return null; 
            }
        } 

        /// 
        /// Boostrapping all the canonical functions for the EDM Provider Manifest
        ///  
        private void InitializeCanonicalFunctions()
        { 
            if (_functions != null) 
            {
                return; 
            }

            List functions = new List();
 
            // Ensure primitive types are available
            InitializePrimitiveTypes(); 
 
            // Initialize all the various parameter types. We do not want to create new instance of parameter types
            // again and again for perf reasons 
            TypeUsage[] parameterTypeUsages = new TypeUsage[EdmConstants.NumPrimitiveTypes];
            Func CreateFirstParameter = (ptk, name) => new FunctionParameter(name, parameterTypeUsages[(int)ptk], ParameterMode.In);
            Func CreateSecondParameter = (ptk, name) => new FunctionParameter(name, parameterTypeUsages[(int)ptk], ParameterMode.In);
            Func CreateThirdParameter = (ptk, name) => new FunctionParameter(name, parameterTypeUsages[(int)ptk], ParameterMode.In); 
            Func CreateFourthParameter = (ptk, name) => new FunctionParameter(name, parameterTypeUsages[(int)ptk], ParameterMode.In);
            Func CreateFifthParameter = (ptk, name) => new FunctionParameter(name, parameterTypeUsages[(int)ptk], ParameterMode.In); 
            Func CreateSixthParameter = (ptk, name) => new FunctionParameter(name, parameterTypeUsages[(int)ptk], ParameterMode.In); 
            Func CreateSeventhParameter = (ptk, name) => new FunctionParameter(name, parameterTypeUsages[(int)ptk], ParameterMode.In);
            Func CreateReturnParameter = ptk => new FunctionParameter(EdmConstants.ReturnType, parameterTypeUsages[(int)ptk], ParameterMode.ReturnValue); 
            Func CreateFirstParametersCollectionType = ptk => new FunctionParameter("collection", TypeUsage.Create(parameterTypeUsages[(int)ptk].EdmType.GetCollectionType()), ParameterMode.In);
            for (int i = 0; i < EdmConstants.NumPrimitiveTypes; i++)
            {
                parameterTypeUsages[i] = TypeUsage.Create(_primitiveTypes[i]); 
            }
 
            #region Aggregate Functions 

            // function overloads for Max, Min and Sum 
            string[] functionNames = { "Max", "Min" };
            PrimitiveTypeKind[] parameterTypes = { PrimitiveTypeKind.Byte,
                                     PrimitiveTypeKind.DateTime,
                                     PrimitiveTypeKind.Decimal, 
                                     PrimitiveTypeKind.Double,
                                     PrimitiveTypeKind.Int16, 
                                     PrimitiveTypeKind.Int32, 
                                     PrimitiveTypeKind.Int64,
                                     PrimitiveTypeKind.SByte, 
                                     PrimitiveTypeKind.Single,
                                     PrimitiveTypeKind.String,
                                     PrimitiveTypeKind.Binary,
                                     PrimitiveTypeKind.Time, 
                                     PrimitiveTypeKind.DateTimeOffset
                                   }; 
 
            foreach (string functionName in functionNames)
            { 
                foreach (PrimitiveTypeKind kind in parameterTypes)
                {
                    EdmFunction function = CreateAggregateCannonicalFunction( functionName,
                                                            CreateReturnParameter(kind), 
                                                            CreateFirstParametersCollectionType(kind));
                    functions.Add(function); 
                } 
            }
 
            string[] functionNames1 = { "Avg", "Sum" };

            PrimitiveTypeKind[] aggregateParameterTypes = { PrimitiveTypeKind.Decimal,
                                              PrimitiveTypeKind.Double, 
                                              PrimitiveTypeKind.Int32,
                                              PrimitiveTypeKind.Int64 }; 
 
            foreach (string functionName in functionNames1)
            { 
                foreach (PrimitiveTypeKind kind in aggregateParameterTypes)
                {
                    EdmFunction function = CreateAggregateCannonicalFunction(functionName,
                                                           CreateReturnParameter(kind), 
                                                           CreateFirstParametersCollectionType(kind));
                    functions.Add(function); 
                } 
            }
 
            // STDEV, STDEVP, VAR, VARP
            string[] statisticalFunctionNames = {"StDev", "StDevP", "Var", "VarP"};
            PrimitiveTypeKind[] statisticalFunctionParameterTypes = { PrimitiveTypeKind.Decimal,
                                          PrimitiveTypeKind.Double, 
                                          PrimitiveTypeKind.Int32,
                                          PrimitiveTypeKind.Int64}; 
            foreach (string functionName in statisticalFunctionNames) 
            {
                foreach (PrimitiveTypeKind kind in statisticalFunctionParameterTypes) 
                {
                    EdmFunction function = CreateAggregateCannonicalFunction(functionName,
                                                            CreateReturnParameter(PrimitiveTypeKind.Double),
                                                            CreateFirstParametersCollectionType(kind)); 
                    functions.Add(function);
                } 
            } 

            // Count and Big Count must be supported for all edm types 
            for (int kindIndex = 0; kindIndex < EdmConstants.NumPrimitiveTypes; kindIndex++)
            {
                PrimitiveTypeKind kind = (PrimitiveTypeKind)kindIndex;
                EdmFunction function = CreateAggregateCannonicalFunction("Count", 
                                                        CreateReturnParameter(PrimitiveTypeKind.Int32),
                                                        CreateFirstParametersCollectionType(kind)); 
                functions.Add(function); 
            }
 
            for (int kindIndex = 0; kindIndex < EdmConstants.NumPrimitiveTypes; kindIndex++)
            {
                PrimitiveTypeKind kind = (PrimitiveTypeKind)kindIndex;
                EdmFunction function = CreateAggregateCannonicalFunction("BigCount", 
                                                        CreateReturnParameter(PrimitiveTypeKind.Int64),
                                                        CreateFirstParametersCollectionType(kind)); 
                functions.Add(function); 
            }
            #endregion 

            #region String Functions

            functions.Add(CreateCannonicalFunction("Trim", 
                                          CreateReturnParameter(PrimitiveTypeKind.String),
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"))); 
 
            functions.Add(CreateCannonicalFunction("RTrim",
                                          CreateReturnParameter(PrimitiveTypeKind.String), 
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument")));

            functions.Add(CreateCannonicalFunction("LTrim",
                                          CreateReturnParameter(PrimitiveTypeKind.String), 
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument")));
 
            functions.Add(CreateCannonicalFunction("Concat", 
                                          CreateReturnParameter(PrimitiveTypeKind.String),
                                          CreateFirstParameter(PrimitiveTypeKind.String, "string1"), 
                                          CreateSecondParameter(PrimitiveTypeKind.String, "string2")));

            functions.Add(CreateCannonicalFunction("Length",
                                          CreateReturnParameter(PrimitiveTypeKind.Int32), 
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument")));
 
            // Substring, Left, Right overloads 
            PrimitiveTypeKind[] subStringParameterTypes = { PrimitiveTypeKind.Byte,
                                              PrimitiveTypeKind.Int16, 
                                              PrimitiveTypeKind.Int32,
                                              PrimitiveTypeKind.Int64,
                                              PrimitiveTypeKind.SByte };
 
            foreach (PrimitiveTypeKind kind in subStringParameterTypes)
            { 
                functions.Add(CreateCannonicalFunction("Substring", 
                                              CreateReturnParameter(PrimitiveTypeKind.String),
                                              CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"), 
                                              CreateSecondParameter(kind, "start"),
                                              CreateThirdParameter(kind, "length")));
            }
 
            foreach (PrimitiveTypeKind kind in subStringParameterTypes)
            { 
                functions.Add(CreateCannonicalFunction("Left", 
                                              CreateReturnParameter(PrimitiveTypeKind.String),
                                              CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"), 
                                              CreateSecondParameter(kind, "length")));
            }

            foreach (PrimitiveTypeKind kind in subStringParameterTypes) 
            {
                functions.Add(CreateCannonicalFunction("Right", 
                                              CreateReturnParameter(PrimitiveTypeKind.String), 
                                              CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"),
                                              CreateSecondParameter(kind, "length"))); 
            }

            functions.Add(CreateCannonicalFunction("Replace",
                                          CreateReturnParameter(PrimitiveTypeKind.String), 
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"),
                                          CreateSecondParameter(PrimitiveTypeKind.String, "toReplace"), 
                                          CreateThirdParameter(PrimitiveTypeKind.String, "replacement"))); 

            functions.Add(CreateCannonicalFunction("IndexOf", 
                                          CreateReturnParameter(PrimitiveTypeKind.Int32),
                                          CreateFirstParameter(PrimitiveTypeKind.String, "searchString"),
                                          CreateSecondParameter(PrimitiveTypeKind.String, "stringToFind")));
 
            functions.Add(CreateCannonicalFunction("ToUpper",
                                          CreateReturnParameter(PrimitiveTypeKind.String), 
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"))); 

            functions.Add(CreateCannonicalFunction("ToLower", 
                                          CreateReturnParameter(PrimitiveTypeKind.String),
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument")));

            functions.Add(CreateCannonicalFunction("Reverse", 
                                          CreateReturnParameter(PrimitiveTypeKind.String),
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"))); 
 
            functions.Add(CreateCannonicalFunction("Contains",
                                         CreateReturnParameter(PrimitiveTypeKind.Boolean), 
                                         CreateFirstParameter(PrimitiveTypeKind.String, "searchedString"),
                                         CreateSecondParameter(PrimitiveTypeKind.String, "searchedForString")));

            functions.Add(CreateCannonicalFunction("StartsWith", 
                                         CreateReturnParameter(PrimitiveTypeKind.Boolean),
                                         CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"), 
                                         CreateSecondParameter(PrimitiveTypeKind.String, "prefix"))); 

            functions.Add(CreateCannonicalFunction("EndsWith", 
                                         CreateReturnParameter(PrimitiveTypeKind.Boolean),
                                         CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"),
                                         CreateSecondParameter(PrimitiveTypeKind.String, "suffix")));
            #endregion // String Functions 

            #region DateTime Functions 
            string[] dateTimeFunctions = { "Year", "Month", "Day", "DayOfYear" }; 

            PrimitiveTypeKind[] dateTimeParameterTypes = { PrimitiveTypeKind.DateTimeOffset, 
                                             PrimitiveTypeKind.DateTime,
                                           };
            foreach (string dateTimeFunction in dateTimeFunctions)
            { 
                foreach (PrimitiveTypeKind kind in dateTimeParameterTypes)
                { 
                    functions.Add(CreateCannonicalFunction(dateTimeFunction, 
                                                  CreateReturnParameter(PrimitiveTypeKind.Int32),
                                                  CreateFirstParameter(kind, "dateValue"))); 
                }
            }

            string[] timeFunctions = { "Hour", "Minute", "Second", "Millisecond" }; 

            PrimitiveTypeKind[] timeParameterTypes = { PrimitiveTypeKind.DateTimeOffset, 
                                         PrimitiveTypeKind.DateTime, 
                                         PrimitiveTypeKind.Time,
                                       }; 
            foreach (string timeFunction in timeFunctions)
            {
                foreach (PrimitiveTypeKind kind in timeParameterTypes)
                { 
                    functions.Add(CreateCannonicalFunction(timeFunction,
                                          CreateReturnParameter(PrimitiveTypeKind.Int32), 
                                          CreateFirstParameter(kind, "timeValue"))); 
                }
            } 


            EdmFunction dateFunction = CreateCannonicalFunction("CurrentDateTime",
                                                                 CreateReturnParameter(PrimitiveTypeKind.DateTime)); 
            functions.Add(dateFunction);
 
            EdmFunction dateTimeOffsetFunction = CreateCannonicalFunction("CurrentDateTimeOffset", 
                                           CreateReturnParameter(PrimitiveTypeKind.DateTimeOffset));
            functions.Add(dateTimeOffsetFunction); 

            functions.Add(CreateCannonicalFunction("GetTotalOffsetMinutes",
                                                  CreateReturnParameter(PrimitiveTypeKind.Int32),
                                                  CreateFirstParameter(PrimitiveTypeKind.DateTimeOffset, "dateTimeOffsetArgument"))); 

            dateFunction = CreateCannonicalFunction("CurrentUtcDateTime", 
                               CreateReturnParameter(PrimitiveTypeKind.DateTime)); 
            functions.Add(dateFunction);
 
            //TruncateTime
            foreach (PrimitiveTypeKind kind in dateTimeParameterTypes)
            {
                functions.Add(CreateCannonicalFunction("TruncateTime", 
                                              CreateReturnParameter(kind),
                                              CreateFirstParameter(kind, "dateValue"))); 
            } 

            //DateTime constructor 
            functions.Add(CreateCannonicalFunction("CreateDateTime",
                                                CreateReturnParameter(PrimitiveTypeKind.DateTime),
                                                CreateFirstParameter(PrimitiveTypeKind.Int32, "year"),
                                                CreateSecondParameter(PrimitiveTypeKind.Int32, "month"), 
                                                CreateThirdParameter(PrimitiveTypeKind.Int32, "day"),
                                                CreateFourthParameter(PrimitiveTypeKind.Int32, "hour"), 
                                                CreateFifthParameter(PrimitiveTypeKind.Int32, "minute"), 
                                                CreateSixthParameter(PrimitiveTypeKind.Double, "second")));
 

            //DateTimeOffset constructor
            functions.Add(CreateCannonicalFunction("CreateDateTimeOffset",
                                                CreateReturnParameter(PrimitiveTypeKind.DateTimeOffset), 
                                                CreateFirstParameter(PrimitiveTypeKind.Int32, "year"),
                                                CreateSecondParameter(PrimitiveTypeKind.Int32, "month"), 
                                                CreateThirdParameter(PrimitiveTypeKind.Int32, "day"), 
                                                CreateFourthParameter(PrimitiveTypeKind.Int32, "hour"),
                                                CreateFifthParameter(PrimitiveTypeKind.Int32, "minute"), 
                                                CreateSixthParameter(PrimitiveTypeKind.Double, "second"),
                                                CreateSeventhParameter(PrimitiveTypeKind.Int32, "timeZoneOffset")));

            //Time constructor 
            functions.Add(CreateCannonicalFunction("CreateTime",
                                                CreateReturnParameter(PrimitiveTypeKind.Time), 
                                                CreateFirstParameter(PrimitiveTypeKind.Int32, "hour"), 
                                                CreateSecondParameter(PrimitiveTypeKind.Int32, "minute"),
                                                CreateThirdParameter(PrimitiveTypeKind.Double, "second"))); 

            //Date and time addition functions
            string[] dateAddFunctionsNames = new string[] { "AddYears", "AddMonths", "AddDays" };
            foreach (string functionName in dateAddFunctionsNames) 
            {
                foreach (PrimitiveTypeKind kind in dateTimeParameterTypes) 
                { 
                    functions.Add(CreateCannonicalFunction(functionName,
                                              CreateReturnParameter(kind), 
                                              CreateFirstParameter(kind, "dateValue"),
                                              CreateSecondParameter(PrimitiveTypeKind.Int32, "addValue")));
                }
            } 

            string[] timeAddFunctionsNames = new string[] { "AddHours", "AddMinutes", "AddSeconds", "AddMilliseconds", "AddMicroseconds", "AddNanoseconds" }; 
            foreach (string functionName in timeAddFunctionsNames) 
            {
                foreach (PrimitiveTypeKind kind in timeParameterTypes) 
                {
                    functions.Add(CreateCannonicalFunction(functionName,
                                                  CreateReturnParameter(kind),
                                                  CreateFirstParameter(kind, "timeValue"), 
                                                  CreateSecondParameter(PrimitiveTypeKind.Int32, "addValue")));
                } 
            } 

            // Date and time diff functions 
            string[] dateDiffFunctionsNames = new string[] { "DiffYears", "DiffMonths", "DiffDays" };
            foreach (string functionName in dateDiffFunctionsNames)
            {
                foreach (PrimitiveTypeKind kind in dateTimeParameterTypes) 
                {
                    functions.Add(CreateCannonicalFunction(functionName, 
                                                  CreateReturnParameter(PrimitiveTypeKind.Int32), 
                                                  CreateFirstParameter(kind, "dateValue1"),
                                                  CreateSecondParameter(kind, "dateValue2"))); 
                }
            }

            string[] timeDiffFunctionsNames = new string[] { "DiffHours", "DiffMinutes", "DiffSeconds", "DiffMilliseconds", "DiffMicroseconds", "DiffNanoseconds" }; 
            foreach (string functionName in timeDiffFunctionsNames)
            { 
                foreach (PrimitiveTypeKind kind in timeParameterTypes) 
                {
                    functions.Add(CreateCannonicalFunction(functionName, 
                                                  CreateReturnParameter(PrimitiveTypeKind.Int32),
                                                  CreateFirstParameter(kind, "timeValue1"),
                                                  CreateSecondParameter(kind, "timeValue2")));
                } 
            }
 
            #endregion // DateTime Functions 

            #region Math Functions 

            // Overloads for ROUND, FLOOR, CEILING functions
            string[] approximationFunctions1 = { "Round", "Floor", "Ceiling" };
            PrimitiveTypeKind[] approximationFunctions1ParameterTypes = { PrimitiveTypeKind.Single, 
                                          PrimitiveTypeKind.Double,
                                          PrimitiveTypeKind.Decimal }; 
 
            foreach (string functionName in approximationFunctions1)
            { 
                foreach (PrimitiveTypeKind kind in approximationFunctions1ParameterTypes)
                {
                    functions.Add(CreateCannonicalFunction(functionName,
                                                  CreateReturnParameter(kind), 
                                                  CreateFirstParameter(kind, "value")));
                } 
            } 

            // Overloads for ROUND, TRUNCATE 
            string[] approximationFunctions2 = { "Round", "Truncate" };
            PrimitiveTypeKind[] approximationFunctions2ParameterTypes = { PrimitiveTypeKind.Double,
                                          PrimitiveTypeKind.Decimal };
 
            foreach (string functionName in approximationFunctions2)
            { 
                foreach (PrimitiveTypeKind kind in approximationFunctions2ParameterTypes) 
                {
                    functions.Add(CreateCannonicalFunction(functionName, 
                                                  CreateReturnParameter(kind),
                                                  CreateFirstParameter(kind, "value"),
                                                  CreateSecondParameter(PrimitiveTypeKind.Int32, "digits")));
                } 
            }
 
            // Overloads for ABS functions 
            PrimitiveTypeKind[] absParameterTypes = { PrimitiveTypeKind.Decimal,
                                        PrimitiveTypeKind.Double, 
                                        PrimitiveTypeKind.Int16,
                                        PrimitiveTypeKind.Int32,
                                        PrimitiveTypeKind.Int64,
                                        PrimitiveTypeKind.Byte, 
                                        PrimitiveTypeKind.Single };
 
            foreach (PrimitiveTypeKind kind in absParameterTypes) 
            {
                functions.Add(CreateCannonicalFunction("Abs", 
                                              CreateReturnParameter(kind),
                                              CreateFirstParameter(kind, "value")));
            }
 
            // Overloads for POWER functions
            PrimitiveTypeKind[] powerFirstParameterTypes = { PrimitiveTypeKind.Decimal, 
                                        PrimitiveTypeKind.Double, 
                                        PrimitiveTypeKind.Int32,
                                        PrimitiveTypeKind.Int64}; 

            PrimitiveTypeKind[] powerSecondParameterTypes = { PrimitiveTypeKind.Decimal,
                                        PrimitiveTypeKind.Double,
                                        PrimitiveTypeKind.Int64 }; 

            foreach (PrimitiveTypeKind kind1 in powerFirstParameterTypes) 
            { 
                foreach (PrimitiveTypeKind kind2 in powerSecondParameterTypes)
                { 
                    functions.Add(CreateCannonicalFunction("Power",
                                                  CreateReturnParameter(kind1),
                                                  CreateFirstParameter(kind1, "baseArgument"),
                                                  CreateSecondParameter(kind2, "exponent"))); 
                }
            } 
            #endregion // Math Functions 

            #region Bitwise Functions 

            string[] bitwiseFunctions = { "BitwiseAnd", "BitwiseOr", "BitwiseXor" };

            // Overloads for BitwiseAND, BitwiseNOT, BitwiseOR, BitwiseXOR functions 
            PrimitiveTypeKind[] bitwiseFunctionOverloads = { PrimitiveTypeKind.Int16,
                                               PrimitiveTypeKind.Int32, 
                                               PrimitiveTypeKind.Int64, 
                                               PrimitiveTypeKind.Byte };
 
            foreach (string functionName in bitwiseFunctions)
            {
                foreach (PrimitiveTypeKind kind in bitwiseFunctionOverloads)
                { 
                    functions.Add(CreateCannonicalFunction(functionName,
                                                  CreateReturnParameter(kind), 
                                                  CreateFirstParameter(kind, "value1"), 
                                                  CreateSecondParameter(kind, "value2")));
                } 
            }

            foreach (PrimitiveTypeKind kind in bitwiseFunctionOverloads)
            { 
                functions.Add(CreateCannonicalFunction("BitwiseNot",
                                              CreateReturnParameter(kind), 
                                              CreateFirstParameter(kind, "value"))); 
            }
            #endregion 

            #region Misc Functions
            functions.Add(CreateCannonicalFunction("NewGuid",
                                          CreateReturnParameter(PrimitiveTypeKind.Guid))); 
            #endregion // Misc Functions
 
            //Set all the functions to readonly 
            foreach (EdmFunction function in functions)
            { 
                function.SetReadOnly();
            }

            System.Collections.ObjectModel.ReadOnlyCollection readOnlyFunctions = new System.Collections.ObjectModel.ReadOnlyCollection(functions); 

            Interlocked.CompareExchange>(ref _functions, readOnlyFunctions, null); 
        } 

        private static EdmFunction CreateAggregateCannonicalFunction(string name, FunctionParameter returnParameter, FunctionParameter parameter) 
        {
            Debug.Assert(name != null && returnParameter != null && parameter != null, "did you choose the wrong overload");

            EdmFunction function = new EdmFunction( name, 
                EdmConstants.EdmNamespace,
                DataSpace.CSpace, 
                new EdmFunctionPayload 
                {
                    IsAggregate = true, 
                    IsBuiltIn = true,
                    ReturnParameter = returnParameter,
                    Parameters = new FunctionParameter[1] { parameter },
                }); 
            return function;
 
        } 

        private static EdmFunction CreateCannonicalFunction(string name, FunctionParameter returnParameter, params FunctionParameter []  parameters) 
        {
            Debug.Assert(name != null && returnParameter != null && parameters != null, "did you choose the wrong overload");

            EdmFunction function = new EdmFunction(name, 
                EdmConstants.EdmNamespace,
                DataSpace.CSpace, 
                new EdmFunctionPayload 
                {
                    IsBuiltIn = true, 
                    ReturnParameter = returnParameter,
                    Parameters = parameters,
                });
            return function; 

        } 
 
        #region Edm Provider Specific Functionality
        ///  
        /// Returns the list of super-types for the given primitiveType
        /// 
        /// 
        ///  
        internal System.Collections.ObjectModel.ReadOnlyCollection GetPromotionTypes(PrimitiveType primitiveType)
        { 
            InitializePromotableTypes(); 

            return _promotionTypes[(int)primitiveType.PrimitiveTypeKind]; 
        }

        /// 
        /// Initializes Promotion Type relation 
        /// 
        private void InitializePromotableTypes() 
        { 
            if (null != _promotionTypes)
            { 
                return;
            }

            System.Collections.ObjectModel.ReadOnlyCollection[] promotionTypes = new System.Collections.ObjectModel.ReadOnlyCollection[EdmConstants.NumPrimitiveTypes]; 

            for (int i = 0; i < EdmConstants.NumPrimitiveTypes; i++) 
            { 
                promotionTypes[i] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] { _primitiveTypes[i] });
            } 

            //
            // PrimitiveTypeKind.Byte
            // 
            promotionTypes[(int)PrimitiveTypeKind.Byte] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] {
                _primitiveTypes[(int)PrimitiveTypeKind.Byte], 
                _primitiveTypes[(int)PrimitiveTypeKind.Int16], 
                _primitiveTypes[(int)PrimitiveTypeKind.Int32],
                _primitiveTypes[(int)PrimitiveTypeKind.Int64], 
                _primitiveTypes[(int)PrimitiveTypeKind.Decimal],
                _primitiveTypes[(int)PrimitiveTypeKind.Single],
                _primitiveTypes[(int)PrimitiveTypeKind.Double]
            }); 

            // 
            // PrimitiveTypeKind.Int16 
            //
            promotionTypes[(int)PrimitiveTypeKind.Int16] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] { 
                _primitiveTypes[(int)PrimitiveTypeKind.Int16],
                _primitiveTypes[(int)PrimitiveTypeKind.Int32],
                _primitiveTypes[(int)PrimitiveTypeKind.Int64],
                _primitiveTypes[(int)PrimitiveTypeKind.Decimal], 
                _primitiveTypes[(int)PrimitiveTypeKind.Single],
                _primitiveTypes[(int)PrimitiveTypeKind.Double] 
            }); 

            // 
            // PrimitiveTypeKind.Int32
            //
            promotionTypes[(int)PrimitiveTypeKind.Int32] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] {
                _primitiveTypes[(int)PrimitiveTypeKind.Int32], 
                _primitiveTypes[(int)PrimitiveTypeKind.Int64],
                _primitiveTypes[(int)PrimitiveTypeKind.Decimal], 
                _primitiveTypes[(int)PrimitiveTypeKind.Single], 
                _primitiveTypes[(int)PrimitiveTypeKind.Double]
            }); 

            //
            // PrimitiveTypeKind.Int64
            // 
            promotionTypes[(int)PrimitiveTypeKind.Int64] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] {
                _primitiveTypes[(int)PrimitiveTypeKind.Int64], 
                _primitiveTypes[(int)PrimitiveTypeKind.Decimal], 
                _primitiveTypes[(int)PrimitiveTypeKind.Single],
                _primitiveTypes[(int)PrimitiveTypeKind.Double] 
            });

            //
            // PrimitiveTypeKind.Single 
            //
            promotionTypes[(int)PrimitiveTypeKind.Single] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] { 
                _primitiveTypes[(int)PrimitiveTypeKind.Single], 
                _primitiveTypes[(int)PrimitiveTypeKind.Double]
            }); 

            Interlocked.CompareExchange[]>(ref _promotionTypes,
                                                                             promotionTypes,
                                                                             null); 
        }
 
        internal TypeUsage GetCanonicalModelTypeUsage(PrimitiveTypeKind primitiveTypeKind) 
        {
            if (null == _canonicalModelTypes) 
            {
                InitializeCanonicalModelTypes();
            }
            return _canonicalModelTypes[(int)primitiveTypeKind]; 
        }
 
        ///  
        /// Initializes Canonical Model Types
        ///  
        private void InitializeCanonicalModelTypes()
        {
            InitializePrimitiveTypes();
 
            TypeUsage[] canonicalTypes = new TypeUsage[EdmConstants.NumPrimitiveTypes];
            for (int primitiveTypeIndex = 0; primitiveTypeIndex < EdmConstants.NumPrimitiveTypes; primitiveTypeIndex++) 
            { 
                PrimitiveType primitiveType = _primitiveTypes[primitiveTypeIndex];
                TypeUsage typeUsage = TypeUsage.CreateDefaultTypeUsage(primitiveType); 
                Debug.Assert(null != typeUsage, "TypeUsage must not be null");
                canonicalTypes[primitiveTypeIndex] = typeUsage;
            }
 
            Interlocked.CompareExchange(ref _canonicalModelTypes, canonicalTypes, null);
        } 
        #endregion 

        #region DbProviderManifest Interface 
        /// 
        /// Returns all the primitive types supported by the provider manifest
        /// 
        /// A collection of primitive types 
        public override System.Collections.ObjectModel.ReadOnlyCollection GetStoreTypes()
        { 
            InitializePrimitiveTypes(); 
            return _primitiveTypes;
        } 

        public override TypeUsage GetEdmType(TypeUsage storeType)
        {
            throw new NotImplementedException(); 
        }
 
        public override TypeUsage GetStoreType(TypeUsage edmType) 
        {
            throw new NotImplementedException(); 
        }

        internal TypeUsage ForgetScalarConstraints(TypeUsage type)
        { 
            PrimitiveType primitiveType = type.EdmType as PrimitiveType;
            Debug.Assert(primitiveType != null, "type argument must be primitive in order to use this function"); 
            if (primitiveType != null) 
            {
                return GetCanonicalModelTypeUsage(primitiveType.PrimitiveTypeKind); 
            }
            else
            {
                return type; 
            }
        } 
 
        /// 
        /// Providers should override this to return information specific to their provider. 
        ///
        /// This method should never return null.
        /// 
        /// The name of the information to be retrieved. 
        /// An XmlReader at the begining of the information requested.
        protected override System.Xml.XmlReader GetDbInformation(string informationType) 
        { 
            throw new NotImplementedException();
        } 
        #endregion

    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System.Data.Common; 
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Threading; 

namespace System.Data.Metadata.Edm 
{ 
    internal class EdmProviderManifest : DbProviderManifest
    { 
        /// 
        /// The ConcurrencyMode Facet Name
        /// 
        internal const string ConcurrencyModeFacetName = "ConcurrencyMode"; 
        /// 
        /// The StoreGeneratedPattern Facet Name 
        ///  
        internal const string StoreGeneratedPatternFacetName = "StoreGeneratedPattern";
        private Dictionary> _facetDescriptions; 
        private System.Collections.ObjectModel.ReadOnlyCollection _primitiveTypes;
        private System.Collections.ObjectModel.ReadOnlyCollection _functions;
        private static EdmProviderManifest _instance = new EdmProviderManifest();
        private System.Collections.ObjectModel.ReadOnlyCollection[] _promotionTypes; 
        static TypeUsage[] _canonicalModelTypes;
 
        internal const byte MaximumDecimalPrecision = Byte.MaxValue; 
        internal const byte MaximumDateTimePrecision = Byte.MaxValue;
 
        /// 
        /// A private constructor to prevent other places from instantiating this class
        /// 
        private EdmProviderManifest() 
        {
        } 
 
        /// 
        /// Gets the EDM provider manifest singleton instance 
        /// 
        internal static EdmProviderManifest Instance
        {
            get 
            {
                return _instance; 
            } 
        }
 
        /// 
        /// Returns the namespace used by this provider manifest
        /// 
        public override string NamespaceName 
        {
            get { return EdmConstants.EdmNamespace; } 
        } 

        ///  
        /// Store version hint
        /// 
        internal string Token
        { 
            // we shouldn't throw exception on properties
            get { return String.Empty; } 
        } 

        ///  
        /// Returns the list of all the canonical functions
        /// 
        /// 
        public override System.Collections.ObjectModel.ReadOnlyCollection GetStoreFunctions() 
        {
            InitializeCanonicalFunctions(); 
            return _functions; 
        }
 
        /// 
        /// Returns all the FacetDescriptions for a particular type
        /// 
        /// the type to return FacetDescriptions for. 
        /// The FacetDescriptions for the type given.
        public override System.Collections.ObjectModel.ReadOnlyCollection GetFacetDescriptions(EdmType type) 
        { 
            Debug.Assert(type is PrimitiveType, "EdmProviderManifest.GetFacetDescriptions(): Argument is not a PrimitiveType");
 
            InitializeFacetDescriptions();

            // Some types may not have facets, so just try to get them, if there aren't any, just return an empty list
            System.Collections.ObjectModel.ReadOnlyCollection collection = null; 
            if (_facetDescriptions.TryGetValue(type as PrimitiveType, out collection))
            { 
                return collection; 
            }
            return Helper.EmptyFacetDescriptionEnumerable; 
        }

        /// 
        /// Returns a primitive type from this manifest having the specified primitive type kind 
        /// 
        /// The value specifying the kind of primitive type to return 
        /// A primitive type having the given primitive type kind 
        public PrimitiveType GetPrimitiveType(PrimitiveTypeKind primitiveTypeKind)
        { 
            InitializePrimitiveTypes();
            return _primitiveTypes[(int)primitiveTypeKind];
        }
 
        /// 
        /// Boostrapping all the primitive types for the EDM Provider Manifest 
        ///  
        private void InitializePrimitiveTypes()
        { 
            if (_primitiveTypes != null)
            {
                return;
            } 

            PrimitiveType[] primitiveTypes = new PrimitiveType[EdmConstants.NumPrimitiveTypes]; 
            primitiveTypes[(int)PrimitiveTypeKind.Binary] = new PrimitiveType(); 
            primitiveTypes[(int)PrimitiveTypeKind.Boolean] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.Byte] = new PrimitiveType(); 
            primitiveTypes[(int)PrimitiveTypeKind.DateTime] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.Decimal] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.Double] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.Single] = new PrimitiveType(); 
            primitiveTypes[(int)PrimitiveTypeKind.Guid] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.Int16] = new PrimitiveType(); 
            primitiveTypes[(int)PrimitiveTypeKind.Int32] = new PrimitiveType(); 
            primitiveTypes[(int)PrimitiveTypeKind.Int64] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.SByte] = new PrimitiveType(); 
            primitiveTypes[(int)PrimitiveTypeKind.String] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.Time] = new PrimitiveType();
            primitiveTypes[(int)PrimitiveTypeKind.DateTimeOffset] = new PrimitiveType();
 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Binary], PrimitiveTypeKind.Binary, EdmConstants.Binary, typeof(Byte[]));
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Boolean], PrimitiveTypeKind.Boolean, EdmConstants.Boolean, typeof(Boolean)); 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Byte], PrimitiveTypeKind.Byte, EdmConstants.Byte, typeof(Byte)); 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.DateTime], PrimitiveTypeKind.DateTime, EdmConstants.DateTime, typeof(DateTime));
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Decimal], PrimitiveTypeKind.Decimal, EdmConstants.Decimal, typeof(Decimal)); 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Double], PrimitiveTypeKind.Double, EdmConstants.Double, typeof(Double));
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Single], PrimitiveTypeKind.Single, EdmConstants.Single, typeof(Single));
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Guid], PrimitiveTypeKind.Guid, EdmConstants.Guid, typeof(Guid));
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Int16], PrimitiveTypeKind.Int16, EdmConstants.Int16, typeof(Int16)); 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Int32], PrimitiveTypeKind.Int32, EdmConstants.Int32, typeof(Int32));
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Int64], PrimitiveTypeKind.Int64, EdmConstants.Int64, typeof(Int64)); 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.SByte], PrimitiveTypeKind.SByte, EdmConstants.SByte, typeof(SByte)); 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.String], PrimitiveTypeKind.String, EdmConstants.String, typeof(String));
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Time], PrimitiveTypeKind.Time, EdmConstants.Time, typeof(TimeSpan)); 
            InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.DateTimeOffset], PrimitiveTypeKind.DateTimeOffset, EdmConstants.DateTimeOffset, typeof(DateTimeOffset));

            // Set all primitive types to be readonly
            foreach (PrimitiveType primitiveType in primitiveTypes) 
            {
                primitiveType.ProviderManifest = this; 
                primitiveType.SetReadOnly(); 
            }
 
            System.Collections.ObjectModel.ReadOnlyCollection readOnlyTypes = new System.Collections.ObjectModel.ReadOnlyCollection(primitiveTypes);

            // Set the result to _primitiveTypes at the end
            Interlocked.CompareExchange>(ref _primitiveTypes, readOnlyTypes, null); 
        }
 
        ///  
        /// Initialize all the primitive type with the given primitive type kind and name
        ///  
        /// The primitive type to initialize
        /// Type of the primitive type which is getting initialized
        /// name of the built in type
        /// the CLR Type of that maps to the EDM PrimitiveType 
        private void InitializePrimitiveType(PrimitiveType primitiveType,
                                             PrimitiveTypeKind primitiveTypeKind, 
                                             string name, 
                                             Type clrType)
        { 
            // Only null types are not abstract and they are sealed, all others are abstract and unsealed
            EdmType.Initialize(primitiveType, name,
                               EdmConstants.EdmNamespace,
                               DataSpace.CSpace, 
                               true /* isabstract */,
                               null /* baseType */); 
            PrimitiveType.Initialize(primitiveType, 
                                     primitiveTypeKind,
                                     true, // isDefault 
                                     this);
            Debug.Assert(clrType == primitiveType.ClrEquivalentType, "ClrEquivalentType mismatch");
        }
 
        /// 
        /// Boostrapping all the facet descriptions for the EDM Provider Manifest 
        ///  
        private void InitializeFacetDescriptions()
        { 
            if (_facetDescriptions != null)
            {
                return;
            } 

            // Ensure the primitive types are there 
            InitializePrimitiveTypes(); 

            // Create the dictionary of facet descriptions 
            Dictionary> facetDescriptions = new Dictionary>();

            // String facets
            FacetDescription[] list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.String); 
            PrimitiveType applicableType = _primitiveTypes[(int)PrimitiveTypeKind.String];
            facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); 
 
            // Binary facets
            list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.Binary); 
            applicableType = _primitiveTypes[(int)PrimitiveTypeKind.Binary];
            facetDescriptions.Add(applicableType, Array.AsReadOnly(list));

            // DateTime facets 
            list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.DateTime);
            applicableType = _primitiveTypes[(int)PrimitiveTypeKind.DateTime]; 
            facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); 

            // Time facets 
            list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.Time);
            applicableType = _primitiveTypes[(int)PrimitiveTypeKind.Time];
            facetDescriptions.Add(applicableType, Array.AsReadOnly(list));
 
            // DateTimeOffset facets
            list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.DateTimeOffset); 
            applicableType = _primitiveTypes[(int)PrimitiveTypeKind.DateTimeOffset]; 
            facetDescriptions.Add(applicableType, Array.AsReadOnly(list));
 

            // Decimal facets
            list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.Decimal);
            applicableType = _primitiveTypes[(int)PrimitiveTypeKind.Decimal]; 
            facetDescriptions.Add(applicableType, Array.AsReadOnly(list));
 
            // Set the result to _facetDescriptions at the end 
            Interlocked.CompareExchange>>(ref _facetDescriptions,
                                                                                                         facetDescriptions, 
                                                                                                         null);
        }

        internal static FacetDescription[] GetInitialFacetDescriptions(PrimitiveTypeKind primitiveTypeKind) 
        {
            FacetDescription[] list; 
 
            switch (primitiveTypeKind)
            { 
                case PrimitiveTypeKind.String:
                    {
                        list = new FacetDescription[3];
 
                        list[0] = (new FacetDescription(DbProviderManifest.MaxLengthFacetName,
                                                      MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Int32), 
                                                      0, 
                                                      Int32.MaxValue,
                                                      null)); 
                        list[1] = (new FacetDescription(DbProviderManifest.UnicodeFacetName,
                                                      MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Boolean),
                                                      null,
                                                      null, 
                                                      null));
                        list[2] = (new FacetDescription(DbProviderManifest.FixedLengthFacetName, 
                                                      MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Boolean), 
                                                      null,
                                                      null, 
                                                      null));

                        return list;
                    } 

                case PrimitiveTypeKind.Binary: 
                    { 
                        list = new FacetDescription[2];
 
                        list[0] = (new FacetDescription(DbProviderManifest.MaxLengthFacetName,
                                                      MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Int32),
                                                      0,
                                                      Int32.MaxValue, 
                                                      null));
                        list[1] = (new FacetDescription(DbProviderManifest.FixedLengthFacetName, 
                                                      MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Boolean), 
                                                      null,
                                                      null, 
                                                      null));
                        return list;
                    }
 
                case PrimitiveTypeKind.DateTime:
                    { 
                        list = new FacetDescription[1]; 

                        list[0] = (new FacetDescription(DbProviderManifest.PrecisionFacetName, 
                              MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte),
                              0, EdmProviderManifest.MaximumDateTimePrecision, null));

                        return list; 
                    }
                case PrimitiveTypeKind.Time: 
                    { 
                        list = new FacetDescription[1];
 
                        list[0] = (new FacetDescription(DbProviderManifest.PrecisionFacetName,
                              MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte),
                              0, EdmProviderManifest.MaximumDateTimePrecision, TypeUsage.DefaultDateTimePrecisionFacetValue));
 
                        return list;
                    } 
                case PrimitiveTypeKind.DateTimeOffset: 
                    {
                        list = new FacetDescription[1]; 
                        list[0] = (new FacetDescription(DbProviderManifest.PrecisionFacetName,
                              MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte),
                              0, EdmProviderManifest.MaximumDateTimePrecision, TypeUsage.DefaultDateTimePrecisionFacetValue));
 
                        return list;
                    } 
                case PrimitiveTypeKind.Decimal: 
                    {
                        list = new FacetDescription[2]; 

                        list[0] = (new FacetDescription(DbProviderManifest.PrecisionFacetName,
                                                      MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte),
                                                      1, 
                                                      EdmProviderManifest.MaximumDecimalPrecision,
                                                      null)); 
                        list[1] = (new FacetDescription(DbProviderManifest.ScaleFacetName, 
                                                      MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte),
                                                      0, 
                                                      EdmProviderManifest.MaximumDecimalPrecision,
                                                      null));
                        return list;
                    } 

                default: 
                    return null; 
            }
        } 

        /// 
        /// Boostrapping all the canonical functions for the EDM Provider Manifest
        ///  
        private void InitializeCanonicalFunctions()
        { 
            if (_functions != null) 
            {
                return; 
            }

            List functions = new List();
 
            // Ensure primitive types are available
            InitializePrimitiveTypes(); 
 
            // Initialize all the various parameter types. We do not want to create new instance of parameter types
            // again and again for perf reasons 
            TypeUsage[] parameterTypeUsages = new TypeUsage[EdmConstants.NumPrimitiveTypes];
            Func CreateFirstParameter = (ptk, name) => new FunctionParameter(name, parameterTypeUsages[(int)ptk], ParameterMode.In);
            Func CreateSecondParameter = (ptk, name) => new FunctionParameter(name, parameterTypeUsages[(int)ptk], ParameterMode.In);
            Func CreateThirdParameter = (ptk, name) => new FunctionParameter(name, parameterTypeUsages[(int)ptk], ParameterMode.In); 
            Func CreateFourthParameter = (ptk, name) => new FunctionParameter(name, parameterTypeUsages[(int)ptk], ParameterMode.In);
            Func CreateFifthParameter = (ptk, name) => new FunctionParameter(name, parameterTypeUsages[(int)ptk], ParameterMode.In); 
            Func CreateSixthParameter = (ptk, name) => new FunctionParameter(name, parameterTypeUsages[(int)ptk], ParameterMode.In); 
            Func CreateSeventhParameter = (ptk, name) => new FunctionParameter(name, parameterTypeUsages[(int)ptk], ParameterMode.In);
            Func CreateReturnParameter = ptk => new FunctionParameter(EdmConstants.ReturnType, parameterTypeUsages[(int)ptk], ParameterMode.ReturnValue); 
            Func CreateFirstParametersCollectionType = ptk => new FunctionParameter("collection", TypeUsage.Create(parameterTypeUsages[(int)ptk].EdmType.GetCollectionType()), ParameterMode.In);
            for (int i = 0; i < EdmConstants.NumPrimitiveTypes; i++)
            {
                parameterTypeUsages[i] = TypeUsage.Create(_primitiveTypes[i]); 
            }
 
            #region Aggregate Functions 

            // function overloads for Max, Min and Sum 
            string[] functionNames = { "Max", "Min" };
            PrimitiveTypeKind[] parameterTypes = { PrimitiveTypeKind.Byte,
                                     PrimitiveTypeKind.DateTime,
                                     PrimitiveTypeKind.Decimal, 
                                     PrimitiveTypeKind.Double,
                                     PrimitiveTypeKind.Int16, 
                                     PrimitiveTypeKind.Int32, 
                                     PrimitiveTypeKind.Int64,
                                     PrimitiveTypeKind.SByte, 
                                     PrimitiveTypeKind.Single,
                                     PrimitiveTypeKind.String,
                                     PrimitiveTypeKind.Binary,
                                     PrimitiveTypeKind.Time, 
                                     PrimitiveTypeKind.DateTimeOffset
                                   }; 
 
            foreach (string functionName in functionNames)
            { 
                foreach (PrimitiveTypeKind kind in parameterTypes)
                {
                    EdmFunction function = CreateAggregateCannonicalFunction( functionName,
                                                            CreateReturnParameter(kind), 
                                                            CreateFirstParametersCollectionType(kind));
                    functions.Add(function); 
                } 
            }
 
            string[] functionNames1 = { "Avg", "Sum" };

            PrimitiveTypeKind[] aggregateParameterTypes = { PrimitiveTypeKind.Decimal,
                                              PrimitiveTypeKind.Double, 
                                              PrimitiveTypeKind.Int32,
                                              PrimitiveTypeKind.Int64 }; 
 
            foreach (string functionName in functionNames1)
            { 
                foreach (PrimitiveTypeKind kind in aggregateParameterTypes)
                {
                    EdmFunction function = CreateAggregateCannonicalFunction(functionName,
                                                           CreateReturnParameter(kind), 
                                                           CreateFirstParametersCollectionType(kind));
                    functions.Add(function); 
                } 
            }
 
            // STDEV, STDEVP, VAR, VARP
            string[] statisticalFunctionNames = {"StDev", "StDevP", "Var", "VarP"};
            PrimitiveTypeKind[] statisticalFunctionParameterTypes = { PrimitiveTypeKind.Decimal,
                                          PrimitiveTypeKind.Double, 
                                          PrimitiveTypeKind.Int32,
                                          PrimitiveTypeKind.Int64}; 
            foreach (string functionName in statisticalFunctionNames) 
            {
                foreach (PrimitiveTypeKind kind in statisticalFunctionParameterTypes) 
                {
                    EdmFunction function = CreateAggregateCannonicalFunction(functionName,
                                                            CreateReturnParameter(PrimitiveTypeKind.Double),
                                                            CreateFirstParametersCollectionType(kind)); 
                    functions.Add(function);
                } 
            } 

            // Count and Big Count must be supported for all edm types 
            for (int kindIndex = 0; kindIndex < EdmConstants.NumPrimitiveTypes; kindIndex++)
            {
                PrimitiveTypeKind kind = (PrimitiveTypeKind)kindIndex;
                EdmFunction function = CreateAggregateCannonicalFunction("Count", 
                                                        CreateReturnParameter(PrimitiveTypeKind.Int32),
                                                        CreateFirstParametersCollectionType(kind)); 
                functions.Add(function); 
            }
 
            for (int kindIndex = 0; kindIndex < EdmConstants.NumPrimitiveTypes; kindIndex++)
            {
                PrimitiveTypeKind kind = (PrimitiveTypeKind)kindIndex;
                EdmFunction function = CreateAggregateCannonicalFunction("BigCount", 
                                                        CreateReturnParameter(PrimitiveTypeKind.Int64),
                                                        CreateFirstParametersCollectionType(kind)); 
                functions.Add(function); 
            }
            #endregion 

            #region String Functions

            functions.Add(CreateCannonicalFunction("Trim", 
                                          CreateReturnParameter(PrimitiveTypeKind.String),
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"))); 
 
            functions.Add(CreateCannonicalFunction("RTrim",
                                          CreateReturnParameter(PrimitiveTypeKind.String), 
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument")));

            functions.Add(CreateCannonicalFunction("LTrim",
                                          CreateReturnParameter(PrimitiveTypeKind.String), 
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument")));
 
            functions.Add(CreateCannonicalFunction("Concat", 
                                          CreateReturnParameter(PrimitiveTypeKind.String),
                                          CreateFirstParameter(PrimitiveTypeKind.String, "string1"), 
                                          CreateSecondParameter(PrimitiveTypeKind.String, "string2")));

            functions.Add(CreateCannonicalFunction("Length",
                                          CreateReturnParameter(PrimitiveTypeKind.Int32), 
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument")));
 
            // Substring, Left, Right overloads 
            PrimitiveTypeKind[] subStringParameterTypes = { PrimitiveTypeKind.Byte,
                                              PrimitiveTypeKind.Int16, 
                                              PrimitiveTypeKind.Int32,
                                              PrimitiveTypeKind.Int64,
                                              PrimitiveTypeKind.SByte };
 
            foreach (PrimitiveTypeKind kind in subStringParameterTypes)
            { 
                functions.Add(CreateCannonicalFunction("Substring", 
                                              CreateReturnParameter(PrimitiveTypeKind.String),
                                              CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"), 
                                              CreateSecondParameter(kind, "start"),
                                              CreateThirdParameter(kind, "length")));
            }
 
            foreach (PrimitiveTypeKind kind in subStringParameterTypes)
            { 
                functions.Add(CreateCannonicalFunction("Left", 
                                              CreateReturnParameter(PrimitiveTypeKind.String),
                                              CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"), 
                                              CreateSecondParameter(kind, "length")));
            }

            foreach (PrimitiveTypeKind kind in subStringParameterTypes) 
            {
                functions.Add(CreateCannonicalFunction("Right", 
                                              CreateReturnParameter(PrimitiveTypeKind.String), 
                                              CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"),
                                              CreateSecondParameter(kind, "length"))); 
            }

            functions.Add(CreateCannonicalFunction("Replace",
                                          CreateReturnParameter(PrimitiveTypeKind.String), 
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"),
                                          CreateSecondParameter(PrimitiveTypeKind.String, "toReplace"), 
                                          CreateThirdParameter(PrimitiveTypeKind.String, "replacement"))); 

            functions.Add(CreateCannonicalFunction("IndexOf", 
                                          CreateReturnParameter(PrimitiveTypeKind.Int32),
                                          CreateFirstParameter(PrimitiveTypeKind.String, "searchString"),
                                          CreateSecondParameter(PrimitiveTypeKind.String, "stringToFind")));
 
            functions.Add(CreateCannonicalFunction("ToUpper",
                                          CreateReturnParameter(PrimitiveTypeKind.String), 
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"))); 

            functions.Add(CreateCannonicalFunction("ToLower", 
                                          CreateReturnParameter(PrimitiveTypeKind.String),
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument")));

            functions.Add(CreateCannonicalFunction("Reverse", 
                                          CreateReturnParameter(PrimitiveTypeKind.String),
                                          CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"))); 
 
            functions.Add(CreateCannonicalFunction("Contains",
                                         CreateReturnParameter(PrimitiveTypeKind.Boolean), 
                                         CreateFirstParameter(PrimitiveTypeKind.String, "searchedString"),
                                         CreateSecondParameter(PrimitiveTypeKind.String, "searchedForString")));

            functions.Add(CreateCannonicalFunction("StartsWith", 
                                         CreateReturnParameter(PrimitiveTypeKind.Boolean),
                                         CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"), 
                                         CreateSecondParameter(PrimitiveTypeKind.String, "prefix"))); 

            functions.Add(CreateCannonicalFunction("EndsWith", 
                                         CreateReturnParameter(PrimitiveTypeKind.Boolean),
                                         CreateFirstParameter(PrimitiveTypeKind.String, "stringArgument"),
                                         CreateSecondParameter(PrimitiveTypeKind.String, "suffix")));
            #endregion // String Functions 

            #region DateTime Functions 
            string[] dateTimeFunctions = { "Year", "Month", "Day", "DayOfYear" }; 

            PrimitiveTypeKind[] dateTimeParameterTypes = { PrimitiveTypeKind.DateTimeOffset, 
                                             PrimitiveTypeKind.DateTime,
                                           };
            foreach (string dateTimeFunction in dateTimeFunctions)
            { 
                foreach (PrimitiveTypeKind kind in dateTimeParameterTypes)
                { 
                    functions.Add(CreateCannonicalFunction(dateTimeFunction, 
                                                  CreateReturnParameter(PrimitiveTypeKind.Int32),
                                                  CreateFirstParameter(kind, "dateValue"))); 
                }
            }

            string[] timeFunctions = { "Hour", "Minute", "Second", "Millisecond" }; 

            PrimitiveTypeKind[] timeParameterTypes = { PrimitiveTypeKind.DateTimeOffset, 
                                         PrimitiveTypeKind.DateTime, 
                                         PrimitiveTypeKind.Time,
                                       }; 
            foreach (string timeFunction in timeFunctions)
            {
                foreach (PrimitiveTypeKind kind in timeParameterTypes)
                { 
                    functions.Add(CreateCannonicalFunction(timeFunction,
                                          CreateReturnParameter(PrimitiveTypeKind.Int32), 
                                          CreateFirstParameter(kind, "timeValue"))); 
                }
            } 


            EdmFunction dateFunction = CreateCannonicalFunction("CurrentDateTime",
                                                                 CreateReturnParameter(PrimitiveTypeKind.DateTime)); 
            functions.Add(dateFunction);
 
            EdmFunction dateTimeOffsetFunction = CreateCannonicalFunction("CurrentDateTimeOffset", 
                                           CreateReturnParameter(PrimitiveTypeKind.DateTimeOffset));
            functions.Add(dateTimeOffsetFunction); 

            functions.Add(CreateCannonicalFunction("GetTotalOffsetMinutes",
                                                  CreateReturnParameter(PrimitiveTypeKind.Int32),
                                                  CreateFirstParameter(PrimitiveTypeKind.DateTimeOffset, "dateTimeOffsetArgument"))); 

            dateFunction = CreateCannonicalFunction("CurrentUtcDateTime", 
                               CreateReturnParameter(PrimitiveTypeKind.DateTime)); 
            functions.Add(dateFunction);
 
            //TruncateTime
            foreach (PrimitiveTypeKind kind in dateTimeParameterTypes)
            {
                functions.Add(CreateCannonicalFunction("TruncateTime", 
                                              CreateReturnParameter(kind),
                                              CreateFirstParameter(kind, "dateValue"))); 
            } 

            //DateTime constructor 
            functions.Add(CreateCannonicalFunction("CreateDateTime",
                                                CreateReturnParameter(PrimitiveTypeKind.DateTime),
                                                CreateFirstParameter(PrimitiveTypeKind.Int32, "year"),
                                                CreateSecondParameter(PrimitiveTypeKind.Int32, "month"), 
                                                CreateThirdParameter(PrimitiveTypeKind.Int32, "day"),
                                                CreateFourthParameter(PrimitiveTypeKind.Int32, "hour"), 
                                                CreateFifthParameter(PrimitiveTypeKind.Int32, "minute"), 
                                                CreateSixthParameter(PrimitiveTypeKind.Double, "second")));
 

            //DateTimeOffset constructor
            functions.Add(CreateCannonicalFunction("CreateDateTimeOffset",
                                                CreateReturnParameter(PrimitiveTypeKind.DateTimeOffset), 
                                                CreateFirstParameter(PrimitiveTypeKind.Int32, "year"),
                                                CreateSecondParameter(PrimitiveTypeKind.Int32, "month"), 
                                                CreateThirdParameter(PrimitiveTypeKind.Int32, "day"), 
                                                CreateFourthParameter(PrimitiveTypeKind.Int32, "hour"),
                                                CreateFifthParameter(PrimitiveTypeKind.Int32, "minute"), 
                                                CreateSixthParameter(PrimitiveTypeKind.Double, "second"),
                                                CreateSeventhParameter(PrimitiveTypeKind.Int32, "timeZoneOffset")));

            //Time constructor 
            functions.Add(CreateCannonicalFunction("CreateTime",
                                                CreateReturnParameter(PrimitiveTypeKind.Time), 
                                                CreateFirstParameter(PrimitiveTypeKind.Int32, "hour"), 
                                                CreateSecondParameter(PrimitiveTypeKind.Int32, "minute"),
                                                CreateThirdParameter(PrimitiveTypeKind.Double, "second"))); 

            //Date and time addition functions
            string[] dateAddFunctionsNames = new string[] { "AddYears", "AddMonths", "AddDays" };
            foreach (string functionName in dateAddFunctionsNames) 
            {
                foreach (PrimitiveTypeKind kind in dateTimeParameterTypes) 
                { 
                    functions.Add(CreateCannonicalFunction(functionName,
                                              CreateReturnParameter(kind), 
                                              CreateFirstParameter(kind, "dateValue"),
                                              CreateSecondParameter(PrimitiveTypeKind.Int32, "addValue")));
                }
            } 

            string[] timeAddFunctionsNames = new string[] { "AddHours", "AddMinutes", "AddSeconds", "AddMilliseconds", "AddMicroseconds", "AddNanoseconds" }; 
            foreach (string functionName in timeAddFunctionsNames) 
            {
                foreach (PrimitiveTypeKind kind in timeParameterTypes) 
                {
                    functions.Add(CreateCannonicalFunction(functionName,
                                                  CreateReturnParameter(kind),
                                                  CreateFirstParameter(kind, "timeValue"), 
                                                  CreateSecondParameter(PrimitiveTypeKind.Int32, "addValue")));
                } 
            } 

            // Date and time diff functions 
            string[] dateDiffFunctionsNames = new string[] { "DiffYears", "DiffMonths", "DiffDays" };
            foreach (string functionName in dateDiffFunctionsNames)
            {
                foreach (PrimitiveTypeKind kind in dateTimeParameterTypes) 
                {
                    functions.Add(CreateCannonicalFunction(functionName, 
                                                  CreateReturnParameter(PrimitiveTypeKind.Int32), 
                                                  CreateFirstParameter(kind, "dateValue1"),
                                                  CreateSecondParameter(kind, "dateValue2"))); 
                }
            }

            string[] timeDiffFunctionsNames = new string[] { "DiffHours", "DiffMinutes", "DiffSeconds", "DiffMilliseconds", "DiffMicroseconds", "DiffNanoseconds" }; 
            foreach (string functionName in timeDiffFunctionsNames)
            { 
                foreach (PrimitiveTypeKind kind in timeParameterTypes) 
                {
                    functions.Add(CreateCannonicalFunction(functionName, 
                                                  CreateReturnParameter(PrimitiveTypeKind.Int32),
                                                  CreateFirstParameter(kind, "timeValue1"),
                                                  CreateSecondParameter(kind, "timeValue2")));
                } 
            }
 
            #endregion // DateTime Functions 

            #region Math Functions 

            // Overloads for ROUND, FLOOR, CEILING functions
            string[] approximationFunctions1 = { "Round", "Floor", "Ceiling" };
            PrimitiveTypeKind[] approximationFunctions1ParameterTypes = { PrimitiveTypeKind.Single, 
                                          PrimitiveTypeKind.Double,
                                          PrimitiveTypeKind.Decimal }; 
 
            foreach (string functionName in approximationFunctions1)
            { 
                foreach (PrimitiveTypeKind kind in approximationFunctions1ParameterTypes)
                {
                    functions.Add(CreateCannonicalFunction(functionName,
                                                  CreateReturnParameter(kind), 
                                                  CreateFirstParameter(kind, "value")));
                } 
            } 

            // Overloads for ROUND, TRUNCATE 
            string[] approximationFunctions2 = { "Round", "Truncate" };
            PrimitiveTypeKind[] approximationFunctions2ParameterTypes = { PrimitiveTypeKind.Double,
                                          PrimitiveTypeKind.Decimal };
 
            foreach (string functionName in approximationFunctions2)
            { 
                foreach (PrimitiveTypeKind kind in approximationFunctions2ParameterTypes) 
                {
                    functions.Add(CreateCannonicalFunction(functionName, 
                                                  CreateReturnParameter(kind),
                                                  CreateFirstParameter(kind, "value"),
                                                  CreateSecondParameter(PrimitiveTypeKind.Int32, "digits")));
                } 
            }
 
            // Overloads for ABS functions 
            PrimitiveTypeKind[] absParameterTypes = { PrimitiveTypeKind.Decimal,
                                        PrimitiveTypeKind.Double, 
                                        PrimitiveTypeKind.Int16,
                                        PrimitiveTypeKind.Int32,
                                        PrimitiveTypeKind.Int64,
                                        PrimitiveTypeKind.Byte, 
                                        PrimitiveTypeKind.Single };
 
            foreach (PrimitiveTypeKind kind in absParameterTypes) 
            {
                functions.Add(CreateCannonicalFunction("Abs", 
                                              CreateReturnParameter(kind),
                                              CreateFirstParameter(kind, "value")));
            }
 
            // Overloads for POWER functions
            PrimitiveTypeKind[] powerFirstParameterTypes = { PrimitiveTypeKind.Decimal, 
                                        PrimitiveTypeKind.Double, 
                                        PrimitiveTypeKind.Int32,
                                        PrimitiveTypeKind.Int64}; 

            PrimitiveTypeKind[] powerSecondParameterTypes = { PrimitiveTypeKind.Decimal,
                                        PrimitiveTypeKind.Double,
                                        PrimitiveTypeKind.Int64 }; 

            foreach (PrimitiveTypeKind kind1 in powerFirstParameterTypes) 
            { 
                foreach (PrimitiveTypeKind kind2 in powerSecondParameterTypes)
                { 
                    functions.Add(CreateCannonicalFunction("Power",
                                                  CreateReturnParameter(kind1),
                                                  CreateFirstParameter(kind1, "baseArgument"),
                                                  CreateSecondParameter(kind2, "exponent"))); 
                }
            } 
            #endregion // Math Functions 

            #region Bitwise Functions 

            string[] bitwiseFunctions = { "BitwiseAnd", "BitwiseOr", "BitwiseXor" };

            // Overloads for BitwiseAND, BitwiseNOT, BitwiseOR, BitwiseXOR functions 
            PrimitiveTypeKind[] bitwiseFunctionOverloads = { PrimitiveTypeKind.Int16,
                                               PrimitiveTypeKind.Int32, 
                                               PrimitiveTypeKind.Int64, 
                                               PrimitiveTypeKind.Byte };
 
            foreach (string functionName in bitwiseFunctions)
            {
                foreach (PrimitiveTypeKind kind in bitwiseFunctionOverloads)
                { 
                    functions.Add(CreateCannonicalFunction(functionName,
                                                  CreateReturnParameter(kind), 
                                                  CreateFirstParameter(kind, "value1"), 
                                                  CreateSecondParameter(kind, "value2")));
                } 
            }

            foreach (PrimitiveTypeKind kind in bitwiseFunctionOverloads)
            { 
                functions.Add(CreateCannonicalFunction("BitwiseNot",
                                              CreateReturnParameter(kind), 
                                              CreateFirstParameter(kind, "value"))); 
            }
            #endregion 

            #region Misc Functions
            functions.Add(CreateCannonicalFunction("NewGuid",
                                          CreateReturnParameter(PrimitiveTypeKind.Guid))); 
            #endregion // Misc Functions
 
            //Set all the functions to readonly 
            foreach (EdmFunction function in functions)
            { 
                function.SetReadOnly();
            }

            System.Collections.ObjectModel.ReadOnlyCollection readOnlyFunctions = new System.Collections.ObjectModel.ReadOnlyCollection(functions); 

            Interlocked.CompareExchange>(ref _functions, readOnlyFunctions, null); 
        } 

        private static EdmFunction CreateAggregateCannonicalFunction(string name, FunctionParameter returnParameter, FunctionParameter parameter) 
        {
            Debug.Assert(name != null && returnParameter != null && parameter != null, "did you choose the wrong overload");

            EdmFunction function = new EdmFunction( name, 
                EdmConstants.EdmNamespace,
                DataSpace.CSpace, 
                new EdmFunctionPayload 
                {
                    IsAggregate = true, 
                    IsBuiltIn = true,
                    ReturnParameter = returnParameter,
                    Parameters = new FunctionParameter[1] { parameter },
                }); 
            return function;
 
        } 

        private static EdmFunction CreateCannonicalFunction(string name, FunctionParameter returnParameter, params FunctionParameter []  parameters) 
        {
            Debug.Assert(name != null && returnParameter != null && parameters != null, "did you choose the wrong overload");

            EdmFunction function = new EdmFunction(name, 
                EdmConstants.EdmNamespace,
                DataSpace.CSpace, 
                new EdmFunctionPayload 
                {
                    IsBuiltIn = true, 
                    ReturnParameter = returnParameter,
                    Parameters = parameters,
                });
            return function; 

        } 
 
        #region Edm Provider Specific Functionality
        ///  
        /// Returns the list of super-types for the given primitiveType
        /// 
        /// 
        ///  
        internal System.Collections.ObjectModel.ReadOnlyCollection GetPromotionTypes(PrimitiveType primitiveType)
        { 
            InitializePromotableTypes(); 

            return _promotionTypes[(int)primitiveType.PrimitiveTypeKind]; 
        }

        /// 
        /// Initializes Promotion Type relation 
        /// 
        private void InitializePromotableTypes() 
        { 
            if (null != _promotionTypes)
            { 
                return;
            }

            System.Collections.ObjectModel.ReadOnlyCollection[] promotionTypes = new System.Collections.ObjectModel.ReadOnlyCollection[EdmConstants.NumPrimitiveTypes]; 

            for (int i = 0; i < EdmConstants.NumPrimitiveTypes; i++) 
            { 
                promotionTypes[i] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] { _primitiveTypes[i] });
            } 

            //
            // PrimitiveTypeKind.Byte
            // 
            promotionTypes[(int)PrimitiveTypeKind.Byte] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] {
                _primitiveTypes[(int)PrimitiveTypeKind.Byte], 
                _primitiveTypes[(int)PrimitiveTypeKind.Int16], 
                _primitiveTypes[(int)PrimitiveTypeKind.Int32],
                _primitiveTypes[(int)PrimitiveTypeKind.Int64], 
                _primitiveTypes[(int)PrimitiveTypeKind.Decimal],
                _primitiveTypes[(int)PrimitiveTypeKind.Single],
                _primitiveTypes[(int)PrimitiveTypeKind.Double]
            }); 

            // 
            // PrimitiveTypeKind.Int16 
            //
            promotionTypes[(int)PrimitiveTypeKind.Int16] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] { 
                _primitiveTypes[(int)PrimitiveTypeKind.Int16],
                _primitiveTypes[(int)PrimitiveTypeKind.Int32],
                _primitiveTypes[(int)PrimitiveTypeKind.Int64],
                _primitiveTypes[(int)PrimitiveTypeKind.Decimal], 
                _primitiveTypes[(int)PrimitiveTypeKind.Single],
                _primitiveTypes[(int)PrimitiveTypeKind.Double] 
            }); 

            // 
            // PrimitiveTypeKind.Int32
            //
            promotionTypes[(int)PrimitiveTypeKind.Int32] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] {
                _primitiveTypes[(int)PrimitiveTypeKind.Int32], 
                _primitiveTypes[(int)PrimitiveTypeKind.Int64],
                _primitiveTypes[(int)PrimitiveTypeKind.Decimal], 
                _primitiveTypes[(int)PrimitiveTypeKind.Single], 
                _primitiveTypes[(int)PrimitiveTypeKind.Double]
            }); 

            //
            // PrimitiveTypeKind.Int64
            // 
            promotionTypes[(int)PrimitiveTypeKind.Int64] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] {
                _primitiveTypes[(int)PrimitiveTypeKind.Int64], 
                _primitiveTypes[(int)PrimitiveTypeKind.Decimal], 
                _primitiveTypes[(int)PrimitiveTypeKind.Single],
                _primitiveTypes[(int)PrimitiveTypeKind.Double] 
            });

            //
            // PrimitiveTypeKind.Single 
            //
            promotionTypes[(int)PrimitiveTypeKind.Single] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] { 
                _primitiveTypes[(int)PrimitiveTypeKind.Single], 
                _primitiveTypes[(int)PrimitiveTypeKind.Double]
            }); 

            Interlocked.CompareExchange[]>(ref _promotionTypes,
                                                                             promotionTypes,
                                                                             null); 
        }
 
        internal TypeUsage GetCanonicalModelTypeUsage(PrimitiveTypeKind primitiveTypeKind) 
        {
            if (null == _canonicalModelTypes) 
            {
                InitializeCanonicalModelTypes();
            }
            return _canonicalModelTypes[(int)primitiveTypeKind]; 
        }
 
        ///  
        /// Initializes Canonical Model Types
        ///  
        private void InitializeCanonicalModelTypes()
        {
            InitializePrimitiveTypes();
 
            TypeUsage[] canonicalTypes = new TypeUsage[EdmConstants.NumPrimitiveTypes];
            for (int primitiveTypeIndex = 0; primitiveTypeIndex < EdmConstants.NumPrimitiveTypes; primitiveTypeIndex++) 
            { 
                PrimitiveType primitiveType = _primitiveTypes[primitiveTypeIndex];
                TypeUsage typeUsage = TypeUsage.CreateDefaultTypeUsage(primitiveType); 
                Debug.Assert(null != typeUsage, "TypeUsage must not be null");
                canonicalTypes[primitiveTypeIndex] = typeUsage;
            }
 
            Interlocked.CompareExchange(ref _canonicalModelTypes, canonicalTypes, null);
        } 
        #endregion 

        #region DbProviderManifest Interface 
        /// 
        /// Returns all the primitive types supported by the provider manifest
        /// 
        /// A collection of primitive types 
        public override System.Collections.ObjectModel.ReadOnlyCollection GetStoreTypes()
        { 
            InitializePrimitiveTypes(); 
            return _primitiveTypes;
        } 

        public override TypeUsage GetEdmType(TypeUsage storeType)
        {
            throw new NotImplementedException(); 
        }
 
        public override TypeUsage GetStoreType(TypeUsage edmType) 
        {
            throw new NotImplementedException(); 
        }

        internal TypeUsage ForgetScalarConstraints(TypeUsage type)
        { 
            PrimitiveType primitiveType = type.EdmType as PrimitiveType;
            Debug.Assert(primitiveType != null, "type argument must be primitive in order to use this function"); 
            if (primitiveType != null) 
            {
                return GetCanonicalModelTypeUsage(primitiveType.PrimitiveTypeKind); 
            }
            else
            {
                return type; 
            }
        } 
 
        /// 
        /// Providers should override this to return information specific to their provider. 
        ///
        /// This method should never return null.
        /// 
        /// The name of the information to be retrieved. 
        /// An XmlReader at the begining of the information requested.
        protected override System.Xml.XmlReader GetDbInformation(string informationType) 
        { 
            throw new NotImplementedException();
        } 
        #endregion

    }
} 

// 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