private bool LoadAssemblyFromCache(
            Assembly assembly, bool loadReferencedAssemblies, EdmItemCollection edmItemCollection, Action <String> logLoadMessage)
        {
            // Code First already did type loading
            if (OSpaceTypesLoaded)
            {
                return(true);
            }

            // If all the containers (usually only one) have the UseClrTypes annotation then use the Code First loader even
            // when using an EDMX.
            if (edmItemCollection != null)
            {
                var containers = edmItemCollection.GetItems <EntityContainer>();
                if (containers.Any() &&
                    containers.All(
                        c => c.Annotations.Any(
                            a => a.Name == XmlConstants.UseClrTypesAnnotationWithPrefix &&
                            ((string)a.Value).ToUpperInvariant() == "TRUE")))
                {
                    lock (LoadAssemblyLock)
                    {
                        if (!OSpaceTypesLoaded)
                        {
                            new CodeFirstOSpaceLoader().LoadTypes(edmItemCollection, this);

                            Debug.Assert(OSpaceTypesLoaded);
                        }
                        return(true);
                    }
                }
            }

            // Check if its loaded in the cache - if the call is for loading referenced assemblies, make sure that all referenced
            // assemblies are also loaded
            KnownAssemblyEntry entry;

            if (_knownAssemblies.TryGetKnownAssembly(assembly, _loaderCookie, edmItemCollection, out entry))
            {
                // Proceed if only we need to load the referenced assemblies and they are not loaded
                if (loadReferencedAssemblies == false)
                {
                    // don't say we loaded anything, unless we actually did before
                    return(entry.CacheEntry.TypesInAssembly.Count != 0);
                }
                else if (entry.ReferencedAssembliesAreLoaded)
                {
                    // this assembly was part of a all hands reference search
                    return(true);
                }
            }

            lock (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 (_knownAssemblies.TryGetKnownAssembly(assembly, _loaderCookie, edmItemCollection, out entry))
                {
                    // Proceed if only we need to load the referenced assemblies and they are not loaded
                    if (loadReferencedAssemblies == false ||
                        entry.ReferencedAssembliesAreLoaded)
                    {
                        return(true);
                    }
                }

                Dictionary <string, EdmType> typesInLoading;
                List <EdmItemError>          errors;
                var knownAssemblies = new KnownAssembliesSet(_knownAssemblies);

                // Load the assembly from the cache
                AssemblyCache.LoadAssembly(
                    assembly, loadReferencedAssemblies, knownAssemblies, edmItemCollection, logLoadMessage,
                    ref _loaderCookie, 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)
                {
                    // 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. 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 AddRange()
                    AddLoadedTypes(typesInLoading);
                }

                // Update the value of known assemblies
                _knownAssemblies = knownAssemblies;

                return(typesInLoading.Count != 0);
            }
        }