ObjectItemCollection.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Metadata / ObjectItemCollection.cs / 2 / ObjectItemCollection.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....], [....]
//--------------------------------------------------------------------- 
 
using System;
using System.Collections; 
using System.Collections.Generic;
using System.Reflection;
using System.Xml.Serialization;
using System.Xml; 
using System.Xml.Schema;
using System.Data.Common.Utils; 
using System.Diagnostics; 
using System.Collections.ObjectModel;
// Using an alias for this because a lot of names in this namespace conflicts with names in metadata 
using DataClasses = System.Data.Objects.DataClasses;
using System.Globalization;
using System.Data.Entity;
using System.Data.Common; 

namespace System.Data.Metadata.Edm 
{ 
    /// 
    /// Class for representing a collection of items for the object layer. 
    /// Most of the implemetation for actual maintainance of the collection is
    /// done by ItemCollection
    /// 
    public sealed partial class ObjectItemCollection : ItemCollection 
    {
        #region Constructors 
 
        /// 
        /// The ObjectItemCollection that loads metadata from assemblies 
        /// 
        public ObjectItemCollection()
            : base(DataSpace.OSpace)
        { 
            foreach (PrimitiveType type in ClrProviderManifest.Instance.GetStoreTypes())
            { 
                AddInternal(type); 
                _primitiveTypeMaps.Add(type);
            } 
        }
        #endregion

        #region Fields 

        // Cache for primitive type maps for Edm to provider 
        private readonly CacheForPrimitiveTypes _primitiveTypeMaps = new CacheForPrimitiveTypes(); 

        // Used for tracking the loading of an assembly and its referenced assemblies. Though the value of an entry is bool, the logic represented 
        // by an entry is tri-state, the third state represented by a "missing" entry. To summarize:
        // 1. The  associated with an  is "true"  : Specified and all referenced assemblies have been loaded
        // 2. The  associated with an  is "false" : Specified assembly loaded. Its referenced assemblies may not be loaded
        // 3. The  is missing                            : Specified assembly has not been loaded 
        private Dictionary _knownAssemblies = new Dictionary();
 
        // Dictionary which keeps tracks of oc mapping information - the key is the conceptual name of the type 
        // and the value is the reference to the ospace type
        private Dictionary _ocMapping = new Dictionary(); 

        private const string EcmPublicKeyToken = "PublicKeyToken=" + AssemblyRef.EcmaPublicKey;

        private object _loadAssemblyLock = new object(); 

        internal object LoadAssemblyLock 
        { 
            get
            { 
                return _loadAssemblyLock;
            }
        }
 
        internal static IList ViewGenerationAssemblies
        { 
            get 
            {
                return AssemblyCacheEntry.ViewGenerationAssemblies; 
            }
        }

        #endregion 

        #region Methods 
 
        /// Is the assembly and its referened assemblies not expected to have any metadata
        internal static bool ShouldFilterAssembly(string fullName) 
        {
            return (fullName.EndsWith(EcmPublicKeyToken, StringComparison.OrdinalIgnoreCase));
        }
 
        internal static bool IsSchemaAttributePresent(Assembly assembly)
        { 
            return assembly.IsDefined(typeof(DataClasses.EdmSchemaAttribute), false /*inherit*/); 
        }
 
        internal static bool IsCompiledViewGenAttributePresent(Assembly assembly)
        {
            return assembly.IsDefined(typeof(System.Data.Mapping.EntityViewGenerationAttribute), false /*inherit*/);
        } 

        ///  
        /// The method loads the O-space metadata for all the referenced assemblies starting from the given assembly 
        /// in a recursive way.
        /// The assembly should be from Assembly.GetCallingAssembly via one of our public API's. 
        /// 
        /// assembly whose dependency list we are going to traverse
        internal void LoadAllReferencedAssemblies(Assembly assembly)
        { 
            this.LoadAllReferencedAssemblies(assembly, false);
        } 
 
        /// 
        /// The method loads all the referenced assemblies starting from the given assembly in a recursive way. 
        /// The assembly should be from Assembly.GetCallingAssembly via one of our public API's.
        /// 
        /// assembly whose dependency list we are going to traverse
        ///  
        internal void LoadAllReferencedAssemblies(Assembly assembly, bool loadOnlyViewGenInfo)
        { 
            if (loadOnlyViewGenInfo) 
            {
                if (!ShouldFilterAssembly(assembly.FullName)) 
                {
                    lock (this)
                    {
                        CollectIfViewGenAssembly(assembly); 

                        foreach (AssemblyName asmName in assembly.GetReferencedAssemblies()) 
                        { 
                            string fullName = asmName.FullName;
                            if (!ShouldFilterAssembly(fullName)) 
                            {
                                // filter out "known" assemblies to prevent unnecessary loading
                                Bid.Trace(" loadededAssembly='%ls'\n", fullName);
 
                                Assembly loadedAssembly = AssemblyCacheEntry.SafeLoadReferencedAssembly(fullName);
                                if (loadedAssembly == null) 
                                { 
                                    continue;
                                } 

                                CollectIfViewGenAssembly(loadedAssembly);
                            }
                        } 
                    }
                } 
            } 
            else
            { 
                LoadAssemblyFromCache(this, assembly, true /*loadAllReferencedAssemblies*/);
            }
        }
 
        /// 
        /// Load metadata from the given assembly 
        ///  
        /// The assembly from which to load metadata
        /// thrown if assembly argument is null 
        public void LoadFromAssembly(Assembly assembly)
        {
            EntityUtil.CheckArgumentNull(assembly, "assembly");
            EntityBid.Trace(" assembly='%ls'\n", assembly.FullName); 
            LoadAssemblyFromCache(this, assembly, false /*loadAllReferencedAssemblies*/);
            //Since User called LoadFromAssembly, so we should collect the generated views if present 
            //even if the schema attribute is not present 
            if (IsCompiledViewGenAttributePresent(assembly) && !IsSchemaAttributePresent(assembly) )
            { 
                CollectIfViewGenAssembly(assembly);
            }
        }
 
        /// 
        /// Load metadata from the type's assembly. 
        ///  
        /// The type's assembly is loaded into the OSpace ItemCollection
        /// true if the type and all its generic arguments are filtered out (did not attempt to load assembly) 
        internal bool LoadAssemblyForType(Type type)
        {
            bool result;
 
            // InternalLoadFromAssembly will check _knownAssemblies
            result = LoadAssemblyFromCache(this, type.Assembly, false /*loadAllReferencedAssemblies*/); 
 
            if (type.IsGenericType)
            { 
                // recursively load all generic types
                // interesting code paths are ObjectQuery>, ObjectQuery>
                foreach (Type t in type.GetGenericArguments())
                { 
                    result |= LoadAssemblyForType(t);
                } 
            } 
            return result;
        } 

        /// 
        /// internal static method to get the relationship name
        ///  
        /// 
        ///  
        ///  
        internal AssociationType GetRelationshipType(Type entityClrType, string relationshipName, out string fullSearchName)
        { 
            fullSearchName = relationshipName;
            AssociationType associationType;
            if (TryGetItem(relationshipName, out associationType))
            { 
                return associationType;
            } 
            else if (!IsQualifiedName(relationshipName)) 
            {
                // they send us unqualified relationship names, try to make it fully qualified 
                EntityType entityType;
                if (TryGetItem(entityClrType.FullName, out entityType))
                {
                    // get the c-space namespace 
                    string namespaceName = System.Data.EntityModel.SchemaObjectModel.Utils.GetEverythingBeforeLastPeriod(((ClrEntityType)entityType).CSpaceTypeName);
                    fullSearchName = namespaceName + "." + relationshipName; 
                    if(TryGetItem(fullSearchName, out associationType)) 
                    {
                        return associationType; 
                    }
                }
            }
 
            return null;
        } 
 
        /// 
        /// Loads the OSpace types in the assembly and returns them as a dictionary 
        /// 
        /// The assembly to load
        /// A mapping from names to OSpace EdmTypes
        private static Dictionary LoadTypesExpensiveWay(Assembly assembly) 
        {
            Dictionary typesInLoading = null; 
 
            // If the assembly is not one of the filtered assemblies and has the schema attribute
            if (!ShouldFilterAssembly(assembly.FullName) && IsSchemaAttributePresent(assembly)) 
            {
                List errors;
                Dictionary knownAssemblies = new Dictionary();
 
                AssemblyCacheEntry.LoadAssemblyFromCache(assembly, false /*loadAllReferencedAssemblies*/,
                    knownAssemblies, out typesInLoading, out errors); 
 
                // Check for errors
                if (errors.Count != 0) 
                {
                    throw EntityUtil.InvalidSchemaEncountered(Helper.CombineErrorMessage(errors));
                }
            } 

            return typesInLoading; 
        } 

        ///  
        /// internal static method to get the relationship name
        /// 
        /// 
        ///  
        /// 
        internal static AssociationType GetRelationshipTypeExpensiveWay(Type entityClrType, string relationshipName, out string fullSearchName) 
        { 
            fullSearchName = relationshipName;
 
            Dictionary typesInLoading = LoadTypesExpensiveWay(entityClrType.Assembly);
            if (typesInLoading != null)
            {
                EdmType edmType; 
                // Look in typesInLoading for relationship type
                if (typesInLoading.TryGetValue(relationshipName, out edmType) && 
                    Helper.IsRelationshipType(edmType)) 
                {
                    return (AssociationType)edmType; 
                }
                else if (!IsQualifiedName(relationshipName))
                {
                    string namespaceName = GetModelNamespaceForEntityType(typesInLoading, entityClrType); 
                    fullSearchName = namespaceName + "." + relationshipName;
                    if (namespaceName != null && 
                       typesInLoading.TryGetValue(fullSearchName, out edmType) && 
                       Helper.IsRelationshipType(edmType))
                    { 
                        return (AssociationType)edmType;
                    }
                }
            } 
            return null;
        } 
 

 
        /// 
        /// internal static method to get all the AssociationTypes from an assembly
        /// 
        /// The assembly from which to load relationship types 
        /// An enumeration of OSpace AssociationTypes that are present in this assembly
        internal static IEnumerable GetAllRelationshipTypesExpensiveWay(Assembly assembly) 
        { 
            Dictionary typesInLoading = LoadTypesExpensiveWay(assembly);
            if (typesInLoading != null) 
            {
                // Iterate through the EdmTypes looking for AssociationTypes
                foreach (EdmType edmType in typesInLoading.Values)
                { 
                    if (Helper.IsAssociationType(edmType))
                    { 
                        yield return (AssociationType)edmType; 
                    }
                } 
            }
            yield break;
        }
 

        private static string GetModelNamespaceForEntityType(Dictionary typesInLoading,Type entityClrType) 
        { 
 	        EdmType edmType;
            if(typesInLoading.TryGetValue(entityClrType.FullName, out edmType) && 
                Helper.IsEntityType(edmType))
            {
                return System.Data.EntityModel.SchemaObjectModel.Utils.GetEverythingBeforeLastPeriod(((ClrEntityType)edmType).CSpaceTypeName);
            } 

            return null; 
        } 

        private static bool IsQualifiedName(string relationshipName) 
        {
            return relationshipName.Contains(".");
        }
 

        private static bool LoadAssemblyFromCache(ObjectItemCollection objectItemCollection, Assembly assembly, 
            bool loadReferencedAssemblies) 
        {
            if (ShouldFilterAssembly(assembly.FullName)) 
            {
                return false;
            }
 
            // Check if its loaded in the cache - if the call is for loading referenced assemblies, make sure that all referenced
            // assemblies are also loaded 
            bool areReferencedAssembliesLoaded; 
            if (objectItemCollection._knownAssemblies.TryGetValue(assembly, out areReferencedAssembliesLoaded))
            { 
                // Proceed if only we need to load the referenced assemblies and they are not loaded
                if (loadReferencedAssemblies == false || areReferencedAssembliesLoaded == true)
                {
                    return true; 
                }
            } 
 
            // Check for schema attribute - if we need to load all the referenced assemblies, then we should continue
            // even if the root assembly doesn't have the attribute present 
            if (!IsSchemaAttributePresent(assembly) && !loadReferencedAssemblies)
            {
                return false;
            } 

            lock (objectItemCollection.LoadAssemblyLock) 
            { 
                // Check after acquiring the lock, since the known assemblies might have got modified
                // Check if the assembly is already loaded. The reason we need to check if the assembly is already loaded, is that 
                if (objectItemCollection._knownAssemblies.TryGetValue(assembly, out areReferencedAssembliesLoaded))
                {
                    // Proceed if only we need to load the referenced assemblies and they are not loaded
                    if (loadReferencedAssemblies == false || areReferencedAssembliesLoaded == true) 
                    {
                        return true; 
                    } 
                }
 
                Dictionary typesInLoading;
                List errors;
                Dictionary knownAssemblies;
 
                if (objectItemCollection != null)
                { 
                    knownAssemblies = new Dictionary(objectItemCollection._knownAssemblies); 
                }
                else 
                {
                    knownAssemblies = new Dictionary();
                }
 
                // Load the assembly from the cache
                AssemblyCacheEntry.LoadAssemblyFromCache(assembly, loadReferencedAssemblies, knownAssemblies, out typesInLoading, out errors); 
 
                // Throw if we have encountered errors
                if (errors.Count != 0) 
                {
                    throw EntityUtil.InvalidSchemaEncountered(Helper.CombineErrorMessage(errors));
                }
 
                // We can encounter new assemblies, but they may not have any time in them
                if (typesInLoading.Count != 0) 
                { 
                    Debug.Assert(knownAssemblies.Count != objectItemCollection._knownAssemblies.Count,
                        "Since there are no types loaded, some assemblies must have got loaded"); 

                    // No errors, so go ahead and add the types and make them readonly
                    // The existence of the loading lock tells us whether we should be thread safe or not, if we need
                    // to be thread safe, then we need to use AtomicAddRange. We don't need to actually use the lock 
                    // because the caller should have done it already
                    // Recheck the assemblies added, another list is created just to match up the collection type 
                    // taken in by AtomicAddRange() 
                    List globalItems = new List();
                    foreach (EdmType edmType in typesInLoading.Values) 
                    {
                        globalItems.Add(edmType);

                        try 
                        {
                            // Also populate the ocmapping information 
                            if (BuiltInTypeKind.EntityType == edmType.BuiltInTypeKind) 
                            {
                                objectItemCollection._ocMapping.Add(((ClrEntityType)edmType).CSpaceTypeName, edmType); 
                            }
                            else if (BuiltInTypeKind.ComplexType == edmType.BuiltInTypeKind)
                            {
                                objectItemCollection._ocMapping.Add(((ClrComplexType)edmType).CSpaceTypeName, edmType); 
                            }
                            // for rest of the types like relationship type, we do not have oc mapping, so we don't keep 
                            // to keep that information 
                        }
                        catch (ArgumentException e) 
                        {
                            throw new MappingException(Strings.Mapping_CannotMapCLRTypeMultipleTimes(edmType.Identity), e);
                        }
                    } 

                    // Create a new ObjectItemCollection and add all the global items to it. 
                    // Also copy all the existing items from the existing collection 
                    objectItemCollection.AtomicAddRange(globalItems);
 
                    // Update the value of known assemblies
                    objectItemCollection._knownAssemblies = knownAssemblies;

                    foreach (Assembly loadedAssembly in knownAssemblies.Keys) 
                    {
                        CollectIfViewGenAssembly(loadedAssembly); 
                    } 
                }
            } 

            return true;
        }
 
        /// 
        /// Check to see if the assembly has the custom view generation attribute AND 
        /// collect the assembly into the local list if it has cutom attribute. 
        /// 
        ///  
        /// 
        private static void CollectIfViewGenAssembly(Assembly assembly)
        {
            if (assembly.IsDefined(typeof(System.Data.Mapping.EntityViewGenerationAttribute), false /*inherit*/)) 
            {
                if (!AssemblyCacheEntry.ViewGenerationAssemblies.Contains(assembly)) 
                { 
                    AssemblyCacheEntry.ViewGenerationAssemblies.Add(assembly);
                } 
            }
        }

        ///  
        /// Get the list of primitive types for the given space
        ///  
        ///  
        public IEnumerable GetPrimitiveTypes()
        { 
            return _primitiveTypeMaps.GetTypes();
        }

        ///  
        /// The method returns the underlying CLR type for the specified OSpace type argument.
        /// If the DataSpace of the parameter is not OSpace, an ArgumentException is thrown. 
        ///  
        /// The OSpace type to look up
        /// The CLR type of the OSpace argument 
        public Type GetClrType(StructuralType objectSpaceType)
        {
            Type clrType;
            if (!this.TryGetClrType(objectSpaceType, out clrType)) 
            {
                throw EntityUtil.Argument(Strings.FailedToFindClrTypeMapping(objectSpaceType.Identity)); 
            } 

            return clrType; 
        }

        /// 
        /// The method returns the underlying CLR type for the specified OSpace type argument. 
        /// If the DataSpace of the parameter is not OSpace, the method returns false and sets
        /// the out parameter to null. 
        ///  
        /// The OSpace type to look up
        /// The CLR type of the OSpace argument 
        /// true on success, false on failure
        public bool TryGetClrType(StructuralType objectSpaceType, out Type clrType)
        {
            EntityUtil.CheckArgumentNull(objectSpaceType, "objectSpaceType"); 

            if (objectSpaceType.DataSpace != DataSpace.OSpace) 
            { 
                throw EntityUtil.Argument(Strings.ArgumentMustBeOSpaceType, "objectSpaceType");
            } 

            clrType = null;

            if (BuiltInTypeKind.EntityType == objectSpaceType.BuiltInTypeKind) 
            {
                clrType = ((ClrEntityType)objectSpaceType).ClrType; 
            } 
            else
            if (BuiltInTypeKind.ComplexType == objectSpaceType.BuiltInTypeKind) 
            {
                clrType = ((ClrComplexType)objectSpaceType).ClrType;
            }
 
            return clrType != null;
        } 
 
        /// 
        /// Given the canonical primitive type, get the mapping primitive type in the given dataspace 
        /// 
        /// canonical primitive type
        /// The mapped scalar type
        internal override PrimitiveType GetMappedPrimitiveType(PrimitiveTypeKind modelType) 
        {
            PrimitiveType type = null; 
            _primitiveTypeMaps.TryGetType(modelType, null, out type); 
            return type;
        } 

        /// 
        /// Get the OSpace type given the CSpace typename
        ///  
        /// 
        ///  
        ///  
        /// 
        internal bool TryGetOSpaceType(EdmType cspaceType, out EdmType edmType) 
        {
            Debug.Assert(DataSpace.CSpace == cspaceType.DataSpace, "DataSpace should be CSpace");

            // check if there is an entity or complex type mapping with this name 
            if (BuiltInTypeKind.EntityType == cspaceType.BuiltInTypeKind ||
                BuiltInTypeKind.ComplexType == cspaceType.BuiltInTypeKind) 
            { 
                return _ocMapping.TryGetValue(cspaceType.Identity, out edmType);
            } 

            return TryGetItem(cspaceType.Identity, out edmType);
        }
 
        /// 
        /// Given the ospace type, returns the fullname of the mapped cspace type. 
        /// Today, since we allow non-default mapping between entity type and complex type, 
        /// this is only possible for entity and complex type.
        ///  
        /// 
        /// 
        internal static string TryGetMappingCSpaceTypeIdentity(EdmType edmType)
        { 
            Debug.Assert(DataSpace.OSpace == edmType.DataSpace, "DataSpace must be OSpace");
 
            if (BuiltInTypeKind.EntityType == edmType.BuiltInTypeKind) 
            {
                return ((ClrEntityType)edmType).CSpaceTypeName; 
            }
            else if (BuiltInTypeKind.ComplexType == edmType.BuiltInTypeKind)
            {
                return ((ClrComplexType)edmType).CSpaceTypeName; 
            }
 
            return edmType.Identity; 
        }
        #endregion 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....], [....]
//--------------------------------------------------------------------- 
 
using System;
using System.Collections; 
using System.Collections.Generic;
using System.Reflection;
using System.Xml.Serialization;
using System.Xml; 
using System.Xml.Schema;
using System.Data.Common.Utils; 
using System.Diagnostics; 
using System.Collections.ObjectModel;
// Using an alias for this because a lot of names in this namespace conflicts with names in metadata 
using DataClasses = System.Data.Objects.DataClasses;
using System.Globalization;
using System.Data.Entity;
using System.Data.Common; 

namespace System.Data.Metadata.Edm 
{ 
    /// 
    /// Class for representing a collection of items for the object layer. 
    /// Most of the implemetation for actual maintainance of the collection is
    /// done by ItemCollection
    /// 
    public sealed partial class ObjectItemCollection : ItemCollection 
    {
        #region Constructors 
 
        /// 
        /// The ObjectItemCollection that loads metadata from assemblies 
        /// 
        public ObjectItemCollection()
            : base(DataSpace.OSpace)
        { 
            foreach (PrimitiveType type in ClrProviderManifest.Instance.GetStoreTypes())
            { 
                AddInternal(type); 
                _primitiveTypeMaps.Add(type);
            } 
        }
        #endregion

        #region Fields 

        // Cache for primitive type maps for Edm to provider 
        private readonly CacheForPrimitiveTypes _primitiveTypeMaps = new CacheForPrimitiveTypes(); 

        // Used for tracking the loading of an assembly and its referenced assemblies. Though the value of an entry is bool, the logic represented 
        // by an entry is tri-state, the third state represented by a "missing" entry. To summarize:
        // 1. The  associated with an  is "true"  : Specified and all referenced assemblies have been loaded
        // 2. The  associated with an  is "false" : Specified assembly loaded. Its referenced assemblies may not be loaded
        // 3. The  is missing                            : Specified assembly has not been loaded 
        private Dictionary _knownAssemblies = new Dictionary();
 
        // Dictionary which keeps tracks of oc mapping information - the key is the conceptual name of the type 
        // and the value is the reference to the ospace type
        private Dictionary _ocMapping = new Dictionary(); 

        private const string EcmPublicKeyToken = "PublicKeyToken=" + AssemblyRef.EcmaPublicKey;

        private object _loadAssemblyLock = new object(); 

        internal object LoadAssemblyLock 
        { 
            get
            { 
                return _loadAssemblyLock;
            }
        }
 
        internal static IList ViewGenerationAssemblies
        { 
            get 
            {
                return AssemblyCacheEntry.ViewGenerationAssemblies; 
            }
        }

        #endregion 

        #region Methods 
 
        /// Is the assembly and its referened assemblies not expected to have any metadata
        internal static bool ShouldFilterAssembly(string fullName) 
        {
            return (fullName.EndsWith(EcmPublicKeyToken, StringComparison.OrdinalIgnoreCase));
        }
 
        internal static bool IsSchemaAttributePresent(Assembly assembly)
        { 
            return assembly.IsDefined(typeof(DataClasses.EdmSchemaAttribute), false /*inherit*/); 
        }
 
        internal static bool IsCompiledViewGenAttributePresent(Assembly assembly)
        {
            return assembly.IsDefined(typeof(System.Data.Mapping.EntityViewGenerationAttribute), false /*inherit*/);
        } 

        ///  
        /// The method loads the O-space metadata for all the referenced assemblies starting from the given assembly 
        /// in a recursive way.
        /// The assembly should be from Assembly.GetCallingAssembly via one of our public API's. 
        /// 
        /// assembly whose dependency list we are going to traverse
        internal void LoadAllReferencedAssemblies(Assembly assembly)
        { 
            this.LoadAllReferencedAssemblies(assembly, false);
        } 
 
        /// 
        /// The method loads all the referenced assemblies starting from the given assembly in a recursive way. 
        /// The assembly should be from Assembly.GetCallingAssembly via one of our public API's.
        /// 
        /// assembly whose dependency list we are going to traverse
        ///  
        internal void LoadAllReferencedAssemblies(Assembly assembly, bool loadOnlyViewGenInfo)
        { 
            if (loadOnlyViewGenInfo) 
            {
                if (!ShouldFilterAssembly(assembly.FullName)) 
                {
                    lock (this)
                    {
                        CollectIfViewGenAssembly(assembly); 

                        foreach (AssemblyName asmName in assembly.GetReferencedAssemblies()) 
                        { 
                            string fullName = asmName.FullName;
                            if (!ShouldFilterAssembly(fullName)) 
                            {
                                // filter out "known" assemblies to prevent unnecessary loading
                                Bid.Trace(" loadededAssembly='%ls'\n", fullName);
 
                                Assembly loadedAssembly = AssemblyCacheEntry.SafeLoadReferencedAssembly(fullName);
                                if (loadedAssembly == null) 
                                { 
                                    continue;
                                } 

                                CollectIfViewGenAssembly(loadedAssembly);
                            }
                        } 
                    }
                } 
            } 
            else
            { 
                LoadAssemblyFromCache(this, assembly, true /*loadAllReferencedAssemblies*/);
            }
        }
 
        /// 
        /// Load metadata from the given assembly 
        ///  
        /// The assembly from which to load metadata
        /// thrown if assembly argument is null 
        public void LoadFromAssembly(Assembly assembly)
        {
            EntityUtil.CheckArgumentNull(assembly, "assembly");
            EntityBid.Trace(" assembly='%ls'\n", assembly.FullName); 
            LoadAssemblyFromCache(this, assembly, false /*loadAllReferencedAssemblies*/);
            //Since User called LoadFromAssembly, so we should collect the generated views if present 
            //even if the schema attribute is not present 
            if (IsCompiledViewGenAttributePresent(assembly) && !IsSchemaAttributePresent(assembly) )
            { 
                CollectIfViewGenAssembly(assembly);
            }
        }
 
        /// 
        /// Load metadata from the type's assembly. 
        ///  
        /// The type's assembly is loaded into the OSpace ItemCollection
        /// true if the type and all its generic arguments are filtered out (did not attempt to load assembly) 
        internal bool LoadAssemblyForType(Type type)
        {
            bool result;
 
            // InternalLoadFromAssembly will check _knownAssemblies
            result = LoadAssemblyFromCache(this, type.Assembly, false /*loadAllReferencedAssemblies*/); 
 
            if (type.IsGenericType)
            { 
                // recursively load all generic types
                // interesting code paths are ObjectQuery>, ObjectQuery>
                foreach (Type t in type.GetGenericArguments())
                { 
                    result |= LoadAssemblyForType(t);
                } 
            } 
            return result;
        } 

        /// 
        /// internal static method to get the relationship name
        ///  
        /// 
        ///  
        ///  
        internal AssociationType GetRelationshipType(Type entityClrType, string relationshipName, out string fullSearchName)
        { 
            fullSearchName = relationshipName;
            AssociationType associationType;
            if (TryGetItem(relationshipName, out associationType))
            { 
                return associationType;
            } 
            else if (!IsQualifiedName(relationshipName)) 
            {
                // they send us unqualified relationship names, try to make it fully qualified 
                EntityType entityType;
                if (TryGetItem(entityClrType.FullName, out entityType))
                {
                    // get the c-space namespace 
                    string namespaceName = System.Data.EntityModel.SchemaObjectModel.Utils.GetEverythingBeforeLastPeriod(((ClrEntityType)entityType).CSpaceTypeName);
                    fullSearchName = namespaceName + "." + relationshipName; 
                    if(TryGetItem(fullSearchName, out associationType)) 
                    {
                        return associationType; 
                    }
                }
            }
 
            return null;
        } 
 
        /// 
        /// Loads the OSpace types in the assembly and returns them as a dictionary 
        /// 
        /// The assembly to load
        /// A mapping from names to OSpace EdmTypes
        private static Dictionary LoadTypesExpensiveWay(Assembly assembly) 
        {
            Dictionary typesInLoading = null; 
 
            // If the assembly is not one of the filtered assemblies and has the schema attribute
            if (!ShouldFilterAssembly(assembly.FullName) && IsSchemaAttributePresent(assembly)) 
            {
                List errors;
                Dictionary knownAssemblies = new Dictionary();
 
                AssemblyCacheEntry.LoadAssemblyFromCache(assembly, false /*loadAllReferencedAssemblies*/,
                    knownAssemblies, out typesInLoading, out errors); 
 
                // Check for errors
                if (errors.Count != 0) 
                {
                    throw EntityUtil.InvalidSchemaEncountered(Helper.CombineErrorMessage(errors));
                }
            } 

            return typesInLoading; 
        } 

        ///  
        /// internal static method to get the relationship name
        /// 
        /// 
        ///  
        /// 
        internal static AssociationType GetRelationshipTypeExpensiveWay(Type entityClrType, string relationshipName, out string fullSearchName) 
        { 
            fullSearchName = relationshipName;
 
            Dictionary typesInLoading = LoadTypesExpensiveWay(entityClrType.Assembly);
            if (typesInLoading != null)
            {
                EdmType edmType; 
                // Look in typesInLoading for relationship type
                if (typesInLoading.TryGetValue(relationshipName, out edmType) && 
                    Helper.IsRelationshipType(edmType)) 
                {
                    return (AssociationType)edmType; 
                }
                else if (!IsQualifiedName(relationshipName))
                {
                    string namespaceName = GetModelNamespaceForEntityType(typesInLoading, entityClrType); 
                    fullSearchName = namespaceName + "." + relationshipName;
                    if (namespaceName != null && 
                       typesInLoading.TryGetValue(fullSearchName, out edmType) && 
                       Helper.IsRelationshipType(edmType))
                    { 
                        return (AssociationType)edmType;
                    }
                }
            } 
            return null;
        } 
 

 
        /// 
        /// internal static method to get all the AssociationTypes from an assembly
        /// 
        /// The assembly from which to load relationship types 
        /// An enumeration of OSpace AssociationTypes that are present in this assembly
        internal static IEnumerable GetAllRelationshipTypesExpensiveWay(Assembly assembly) 
        { 
            Dictionary typesInLoading = LoadTypesExpensiveWay(assembly);
            if (typesInLoading != null) 
            {
                // Iterate through the EdmTypes looking for AssociationTypes
                foreach (EdmType edmType in typesInLoading.Values)
                { 
                    if (Helper.IsAssociationType(edmType))
                    { 
                        yield return (AssociationType)edmType; 
                    }
                } 
            }
            yield break;
        }
 

        private static string GetModelNamespaceForEntityType(Dictionary typesInLoading,Type entityClrType) 
        { 
 	        EdmType edmType;
            if(typesInLoading.TryGetValue(entityClrType.FullName, out edmType) && 
                Helper.IsEntityType(edmType))
            {
                return System.Data.EntityModel.SchemaObjectModel.Utils.GetEverythingBeforeLastPeriod(((ClrEntityType)edmType).CSpaceTypeName);
            } 

            return null; 
        } 

        private static bool IsQualifiedName(string relationshipName) 
        {
            return relationshipName.Contains(".");
        }
 

        private static bool LoadAssemblyFromCache(ObjectItemCollection objectItemCollection, Assembly assembly, 
            bool loadReferencedAssemblies) 
        {
            if (ShouldFilterAssembly(assembly.FullName)) 
            {
                return false;
            }
 
            // Check if its loaded in the cache - if the call is for loading referenced assemblies, make sure that all referenced
            // assemblies are also loaded 
            bool areReferencedAssembliesLoaded; 
            if (objectItemCollection._knownAssemblies.TryGetValue(assembly, out areReferencedAssembliesLoaded))
            { 
                // Proceed if only we need to load the referenced assemblies and they are not loaded
                if (loadReferencedAssemblies == false || areReferencedAssembliesLoaded == true)
                {
                    return true; 
                }
            } 
 
            // Check for schema attribute - if we need to load all the referenced assemblies, then we should continue
            // even if the root assembly doesn't have the attribute present 
            if (!IsSchemaAttributePresent(assembly) && !loadReferencedAssemblies)
            {
                return false;
            } 

            lock (objectItemCollection.LoadAssemblyLock) 
            { 
                // Check after acquiring the lock, since the known assemblies might have got modified
                // Check if the assembly is already loaded. The reason we need to check if the assembly is already loaded, is that 
                if (objectItemCollection._knownAssemblies.TryGetValue(assembly, out areReferencedAssembliesLoaded))
                {
                    // Proceed if only we need to load the referenced assemblies and they are not loaded
                    if (loadReferencedAssemblies == false || areReferencedAssembliesLoaded == true) 
                    {
                        return true; 
                    } 
                }
 
                Dictionary typesInLoading;
                List errors;
                Dictionary knownAssemblies;
 
                if (objectItemCollection != null)
                { 
                    knownAssemblies = new Dictionary(objectItemCollection._knownAssemblies); 
                }
                else 
                {
                    knownAssemblies = new Dictionary();
                }
 
                // Load the assembly from the cache
                AssemblyCacheEntry.LoadAssemblyFromCache(assembly, loadReferencedAssemblies, knownAssemblies, out typesInLoading, out errors); 
 
                // Throw if we have encountered errors
                if (errors.Count != 0) 
                {
                    throw EntityUtil.InvalidSchemaEncountered(Helper.CombineErrorMessage(errors));
                }
 
                // We can encounter new assemblies, but they may not have any time in them
                if (typesInLoading.Count != 0) 
                { 
                    Debug.Assert(knownAssemblies.Count != objectItemCollection._knownAssemblies.Count,
                        "Since there are no types loaded, some assemblies must have got loaded"); 

                    // No errors, so go ahead and add the types and make them readonly
                    // The existence of the loading lock tells us whether we should be thread safe or not, if we need
                    // to be thread safe, then we need to use AtomicAddRange. We don't need to actually use the lock 
                    // because the caller should have done it already
                    // Recheck the assemblies added, another list is created just to match up the collection type 
                    // taken in by AtomicAddRange() 
                    List globalItems = new List();
                    foreach (EdmType edmType in typesInLoading.Values) 
                    {
                        globalItems.Add(edmType);

                        try 
                        {
                            // Also populate the ocmapping information 
                            if (BuiltInTypeKind.EntityType == edmType.BuiltInTypeKind) 
                            {
                                objectItemCollection._ocMapping.Add(((ClrEntityType)edmType).CSpaceTypeName, edmType); 
                            }
                            else if (BuiltInTypeKind.ComplexType == edmType.BuiltInTypeKind)
                            {
                                objectItemCollection._ocMapping.Add(((ClrComplexType)edmType).CSpaceTypeName, edmType); 
                            }
                            // for rest of the types like relationship type, we do not have oc mapping, so we don't keep 
                            // to keep that information 
                        }
                        catch (ArgumentException e) 
                        {
                            throw new MappingException(Strings.Mapping_CannotMapCLRTypeMultipleTimes(edmType.Identity), e);
                        }
                    } 

                    // Create a new ObjectItemCollection and add all the global items to it. 
                    // Also copy all the existing items from the existing collection 
                    objectItemCollection.AtomicAddRange(globalItems);
 
                    // Update the value of known assemblies
                    objectItemCollection._knownAssemblies = knownAssemblies;

                    foreach (Assembly loadedAssembly in knownAssemblies.Keys) 
                    {
                        CollectIfViewGenAssembly(loadedAssembly); 
                    } 
                }
            } 

            return true;
        }
 
        /// 
        /// Check to see if the assembly has the custom view generation attribute AND 
        /// collect the assembly into the local list if it has cutom attribute. 
        /// 
        ///  
        /// 
        private static void CollectIfViewGenAssembly(Assembly assembly)
        {
            if (assembly.IsDefined(typeof(System.Data.Mapping.EntityViewGenerationAttribute), false /*inherit*/)) 
            {
                if (!AssemblyCacheEntry.ViewGenerationAssemblies.Contains(assembly)) 
                { 
                    AssemblyCacheEntry.ViewGenerationAssemblies.Add(assembly);
                } 
            }
        }

        ///  
        /// Get the list of primitive types for the given space
        ///  
        ///  
        public IEnumerable GetPrimitiveTypes()
        { 
            return _primitiveTypeMaps.GetTypes();
        }

        ///  
        /// The method returns the underlying CLR type for the specified OSpace type argument.
        /// If the DataSpace of the parameter is not OSpace, an ArgumentException is thrown. 
        ///  
        /// The OSpace type to look up
        /// The CLR type of the OSpace argument 
        public Type GetClrType(StructuralType objectSpaceType)
        {
            Type clrType;
            if (!this.TryGetClrType(objectSpaceType, out clrType)) 
            {
                throw EntityUtil.Argument(Strings.FailedToFindClrTypeMapping(objectSpaceType.Identity)); 
            } 

            return clrType; 
        }

        /// 
        /// The method returns the underlying CLR type for the specified OSpace type argument. 
        /// If the DataSpace of the parameter is not OSpace, the method returns false and sets
        /// the out parameter to null. 
        ///  
        /// The OSpace type to look up
        /// The CLR type of the OSpace argument 
        /// true on success, false on failure
        public bool TryGetClrType(StructuralType objectSpaceType, out Type clrType)
        {
            EntityUtil.CheckArgumentNull(objectSpaceType, "objectSpaceType"); 

            if (objectSpaceType.DataSpace != DataSpace.OSpace) 
            { 
                throw EntityUtil.Argument(Strings.ArgumentMustBeOSpaceType, "objectSpaceType");
            } 

            clrType = null;

            if (BuiltInTypeKind.EntityType == objectSpaceType.BuiltInTypeKind) 
            {
                clrType = ((ClrEntityType)objectSpaceType).ClrType; 
            } 
            else
            if (BuiltInTypeKind.ComplexType == objectSpaceType.BuiltInTypeKind) 
            {
                clrType = ((ClrComplexType)objectSpaceType).ClrType;
            }
 
            return clrType != null;
        } 
 
        /// 
        /// Given the canonical primitive type, get the mapping primitive type in the given dataspace 
        /// 
        /// canonical primitive type
        /// The mapped scalar type
        internal override PrimitiveType GetMappedPrimitiveType(PrimitiveTypeKind modelType) 
        {
            PrimitiveType type = null; 
            _primitiveTypeMaps.TryGetType(modelType, null, out type); 
            return type;
        } 

        /// 
        /// Get the OSpace type given the CSpace typename
        ///  
        /// 
        ///  
        ///  
        /// 
        internal bool TryGetOSpaceType(EdmType cspaceType, out EdmType edmType) 
        {
            Debug.Assert(DataSpace.CSpace == cspaceType.DataSpace, "DataSpace should be CSpace");

            // check if there is an entity or complex type mapping with this name 
            if (BuiltInTypeKind.EntityType == cspaceType.BuiltInTypeKind ||
                BuiltInTypeKind.ComplexType == cspaceType.BuiltInTypeKind) 
            { 
                return _ocMapping.TryGetValue(cspaceType.Identity, out edmType);
            } 

            return TryGetItem(cspaceType.Identity, out edmType);
        }
 
        /// 
        /// Given the ospace type, returns the fullname of the mapped cspace type. 
        /// Today, since we allow non-default mapping between entity type and complex type, 
        /// this is only possible for entity and complex type.
        ///  
        /// 
        /// 
        internal static string TryGetMappingCSpaceTypeIdentity(EdmType edmType)
        { 
            Debug.Assert(DataSpace.OSpace == edmType.DataSpace, "DataSpace must be OSpace");
 
            if (BuiltInTypeKind.EntityType == edmType.BuiltInTypeKind) 
            {
                return ((ClrEntityType)edmType).CSpaceTypeName; 
            }
            else if (BuiltInTypeKind.ComplexType == edmType.BuiltInTypeKind)
            {
                return ((ClrComplexType)edmType).CSpaceTypeName; 
            }
 
            return edmType.Identity; 
        }
        #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