storagemappingitemcollection.viewdictionary.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 / Mapping / storagemappingitemcollection.viewdictionary.cs / 1508357 / storagemappingitemcollection.viewdictionary.cs

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

using System.Data.Common.Utils; 
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Data.Common.CommandTrees; 
using System.Data.Metadata.Edm;
using System.Data.Mapping.ViewGeneration; 
using System.Reflection; 
using System.Data.Mapping.Update.Internal;
using System.Linq; 

// All methods prefixed with 'Serialized' have locked access through the shared Memoizer. Do not call it from outside the Memoizer's scope.
namespace System.Data.Mapping
{ 
    using OfTypeQVCacheKey = Pair>;
    using System.Data.Common.CommandTrees.ExpressionBuilder; 
    using System.Data.Mapping.ViewGeneration.Utils; 

    public partial class StorageMappingItemCollection : MappingItemCollection 
    {
        internal delegate bool TryGetUserDefinedQueryView(EntitySetBase extent, out GeneratedView generatedView);
        internal delegate bool TryGetUserDefinedQueryViewOfType(OfTypeQVCacheKey extent, out GeneratedView generatedView);
 
        internal class ViewDictionary
        { 
 
            readonly TryGetUserDefinedQueryView TryGetUserDefinedQueryView;
            readonly TryGetUserDefinedQueryViewOfType TryGetUserDefinedQueryViewOfType; 

            private StorageMappingItemCollection m_storageMappingItemCollection;

            private static ConfigViewGenerator m_config = new ConfigViewGenerator(); 

            // List of assemblies from which we have loaded views from 
            private List m_knownViewGenAssemblies = new List(); 

            // indicates whether the views are being fetched from a generated class or they are being generated at the runtime 
            private bool m_generatedViewsMode = true;

            //Caches computation of view generation (of all EntitySets) for a given EntityContainer
            private readonly Memoizer> m_generatedViewsMemoizer; 

            //Caches computation of getting Type-specific Query Views - either by view gen or user-defined input 
            private readonly Memoizer m_generatedViewOfTypeMemoizer; 

            internal ViewDictionary(StorageMappingItemCollection storageMappingItemCollection, 
                            out Dictionary userDefinedQueryViewsDict,
                            out Dictionary userDefinedQueryViewsOfTypeDict)
            {
                this.m_storageMappingItemCollection = storageMappingItemCollection; 
                this.m_generatedViewsMemoizer = new Memoizer>(SerializedGetGeneratedViews
                    , null); 
                this.m_generatedViewOfTypeMemoizer = new Memoizer(SerializedGeneratedViewOfType, OfTypeQVCacheKey.PairComparer.Instance); 

                userDefinedQueryViewsDict = new Dictionary(EqualityComparer.Default); 
                userDefinedQueryViewsOfTypeDict = new Dictionary(OfTypeQVCacheKey.PairComparer.Instance);

                TryGetUserDefinedQueryView = userDefinedQueryViewsDict.TryGetValue;
                TryGetUserDefinedQueryViewOfType = userDefinedQueryViewsOfTypeDict.TryGetValue; 
            }
 
 
            private Dictionary SerializedGetGeneratedViews(EntityContainer container)
            { 
                Dictionary extentMappingViews = new Dictionary(); ;

                MetadataWorkspace workspace = new MetadataWorkspace();
                workspace.RegisterItemCollection(this.m_storageMappingItemCollection.StoreItemCollection); 
                workspace.RegisterItemCollection(this.m_storageMappingItemCollection.EdmItemCollection);
                workspace.RegisterItemCollection(this.m_storageMappingItemCollection); 
 
                //If we are in generated views mode
                if (m_generatedViewsMode) 
                {
                    if(ObjectItemCollection.ViewGenerationAssemblies!=null && ObjectItemCollection.ViewGenerationAssemblies.Count>0)
                    {
                        SerializedCollectViewsFromObjectCollection(workspace, extentMappingViews); 
                    }
                    else 
                    { 
                        SerializedCollectViewsFromReferencedAssemblies(workspace, extentMappingViews);
                    } 

                    if (this.m_knownViewGenAssemblies.Count != 0)
                    {
                        EntityBid.Trace(" The View generation Mode is Compile Time View Generation\n"); 
                    }
                } 
 
                if (extentMappingViews.Count==0)
                { 
                    //We should change the mode to runtime generation of views.
                    this.m_generatedViewsMode = false;
                    EntityBid.Trace(" The View generation Mode is Runtime View Generation\n");
                    this.SerializedGenerateViews(container, extentMappingViews); 

                } 
 
                Debug.Assert(extentMappingViews.Count>0, "view should be generated at this point");
 
                return extentMappingViews;
            }

            ///  
            /// Call the View Generator's Generate view method
            /// and collect the Views and store it in a local dictionary. 
            ///  
            /// 
            ///  
            private void SerializedGenerateViews(EntityContainer container, Dictionary resultDictionary)
            {
                Debug.Assert(container != null);
 
                //Get the mapping that has the entity container
                //mapped. 
                StorageEntityContainerMapping entityContainerMap = MappingMetadataHelper.GetEntityContainerMap(m_storageMappingItemCollection, container); 
                //If there are no entity set maps, don't call the view generation process
                if (entityContainerMap.IsEmpty) 
                {
                    return;
                }
                ViewGenResults viewGenResults = ViewgenGatekeeper.GenerateViewsFromMapping(entityContainerMap, m_config); 
                KeyToListMap extentMappingViews = viewGenResults.Views;
                if (viewGenResults.HasErrors) 
                { 
                    // Can get the list of errors using viewGenResults.Errors
 
                    throw new MappingException(Helper.CombineErrorMessage(viewGenResults.Errors));
                }

                foreach (KeyValuePair> keyValuePair in extentMappingViews.KeyValuePairs) 
                {
                    //Multiple Views are returned for an extent but the first view 
                    //is the only one that we will use for now. In the future, 
                    //we might start using the other views which are per type within an extent.
                    GeneratedView generatedView; 
                    //Add the view to the local dictionary

                    if (!resultDictionary.TryGetValue(keyValuePair.Key, out generatedView))
                    { 
                        generatedView = keyValuePair.Value[0];
                        resultDictionary.Add(keyValuePair.Key, generatedView); 
                    } 
                }
            } 

            /// 
            /// Generates a single query view for a given Extent and type. It is used to generate OfType and OfTypeOnly views.
            ///  
            /// Whether the view should include extents that are subtypes of the given entity
            private bool TryGenerateQueryViewOfType(EntityContainer entityContainer, EntitySetBase entity, EntityTypeBase type, bool includeSubtypes, out GeneratedView generatedView) 
            { 
                Debug.Assert(entityContainer != null);
                Debug.Assert(entity != null); 
                Debug.Assert(type != null);

                MetadataWorkspace workspace = new MetadataWorkspace();
                workspace.RegisterItemCollection(this.m_storageMappingItemCollection.EdmItemCollection); 
                workspace.RegisterItemCollection(this.m_storageMappingItemCollection.StoreItemCollection);
                workspace.RegisterItemCollection(this.m_storageMappingItemCollection); 
 
                if (type.Abstract)
                { 
                    generatedView = null;
                    return false;
                }
 
                //Get the mapping that has the entity container mapped.
                StorageEntityContainerMapping entityContainerMap = MappingMetadataHelper.GetEntityContainerMap(m_storageMappingItemCollection, entityContainer); 
                Debug.Assert(!entityContainerMap.IsEmpty, "There are no entity set maps"); 

                bool success; 
                ViewGenResults viewGenResults = ViewgenGatekeeper.GenerateTypeSpecificQueryView(entityContainerMap, m_config, entity, type, includeSubtypes, out success);
                if (!success)
                {
                    generatedView = null; 
                    return false; //could not generate view
                } 
 
                KeyToListMap extentMappingViews = viewGenResults.Views;
 
                if (viewGenResults.HasErrors)
                {
                    throw new MappingException(Helper.CombineErrorMessage(viewGenResults.Errors));
                } 

                Debug.Assert(extentMappingViews.AllValues.Count() == 1, "Viewgen should have produced only one view"); 
                generatedView = extentMappingViews.AllValues.First(); 

                return true; 
            }

            /// 
            /// Tries to generate the Oftype or OfTypeOnly query view for a given entity set and type. 
            /// Returns false if the view could not be generated.
            /// Possible reasons for failing are 
            ///   1) Passing in OfTypeOnly on an abstract type 
            ///   2) In user-specified query views mode a query for the given type is absent
            ///  
            internal bool TryGetGeneratedViewOfType(MetadataWorkspace workspace, EntitySetBase entity, EntityTypeBase type, bool includeSubtypes, out GeneratedView generatedView)
            {
                OfTypeQVCacheKey key = new OfTypeQVCacheKey(entity, new Pair(type, includeSubtypes));
                generatedView = this.m_generatedViewOfTypeMemoizer.Evaluate(key); 
                return (generatedView != null);
            } 
 
            /// 
            /// Note: Null return value implies QV was not generated. 
            /// 
            /// 
            private GeneratedView SerializedGeneratedViewOfType(OfTypeQVCacheKey arg)
            { 
                GeneratedView generatedView;
                //See if we have collected user-defined QueryView 
                if(TryGetUserDefinedQueryViewOfType(arg, out generatedView)) 
                {
                    return generatedView; 
                }

                //Now we have to generate the type-specific view
                EntitySetBase entity = arg.First; 
                EntityTypeBase type = arg.Second.First;
                bool includeSubtypes = arg.Second.Second; 
 
                if (!TryGenerateQueryViewOfType(entity.EntityContainer, entity, type, includeSubtypes, out generatedView))
                { 
                    generatedView = null;
                }

                return generatedView; 
            }
 
            ///  
            /// Returns the update or query view for an Extent as a
            /// string. 
            /// There are a series of steps that we go through for discovering a view for an extent.
            /// To start with we assume that we are working with Generated Views. To find out the
            /// generated view we go to the ObjectItemCollection and see if it is not-null. If the ObjectItemCollection
            /// is non-null, we get the view generation assemblies that it might have cached during the 
            /// Object metadata discovery.If there are no view generation assemblies we switch to the
            /// runtime view generation strategy. If there are view generation assemblies, we get the list and 
            /// go through them and see if there are any assemblies that are there from which we have not already loaded 
            /// the views. We collect the views from assemblies that we have not already collected from earlier.
            /// If the ObjectItemCollection is null and we are in the view generation mode, that means that 
            /// the query or update is issued from the Value layer and this is the first time view has been asked for.
            /// The compile time view gen for value layer queries will work for very simple scenarios.
            /// If the users wants to get the performance benefit, they should call MetadataWorkspace.LoadFromAssembly.
            /// At this point we go through the referenced assemblies of the entry assembly( this wont work for Asp.net 
            /// or if the viewgen assembly was not referenced by the executing application).
            /// and try to see if there were any view gen assemblies. If there are, we collect the views for all extents. 
            /// Once we have all the generated views gathered, we try to get the view for the extent passed in. 
            /// If we find one we will return it. If we can't find one an exception will be thrown.
            /// If there were no view gen assemblies either in the ObjectItemCollection or in the list of referenced 
            /// assemblies of calling assembly, we change the mode to runtime view generation and will continue to
            /// be in that mode for the rest of the lifetime of the mapping item collection.
            /// 
            internal GeneratedView GetGeneratedView(EntitySetBase extent, MetadataWorkspace workspace, StorageMappingItemCollection storageMappingItemCollection) 
            {
                //First check if we have collected a view from user-defined query views 
                //Dont need to worry whether to generate Query view or update viw, because that is relative to the extent. 
                GeneratedView view;
 
                if (TryGetUserDefinedQueryView(extent, out view))
                {
                    return view;
                } 

                //If this is a foreign key association, manufacture a view on the fly. 
                if (extent.BuiltInTypeKind == BuiltInTypeKind.AssociationSet) 
                {
                    AssociationSet aSet = (AssociationSet)extent; 
                    if (aSet.ElementType.IsForeignKey)
                    {
                        // Although we expose a collection of constraints in the API, there is only ever one
                        // constraint. 
                        ReferentialConstraint rc = aSet.ElementType.ReferentialConstraints.Single();
                        EntitySet dependentSet = aSet.AssociationSetEnds[rc.ToRole.Name].EntitySet; 
                        EntitySet principalSet = aSet.AssociationSetEnds[rc.FromRole.Name].EntitySet; 

                        // Introduce an OfType view if the dependent end is a subtype of the entity set 
                        EntityType dependentType = MetadataHelper.GetEntityTypeForEnd((AssociationEndMember)rc.ToRole);
                        GeneratedView generatedView = GetGeneratedView(dependentSet, workspace, storageMappingItemCollection);
                        bool introduceOfType = false;
                        if (dependentSet.ElementType.IsBaseTypeOf(dependentType)) 
                        {
                            // First check for an OfType view 
                            GeneratedView ofTypeGeneratedView; 
                            if (TryGetGeneratedViewOfType(workspace, dependentSet, dependentType, true, out ofTypeGeneratedView))
                            { 
                                generatedView = ofTypeGeneratedView;
                            }
                            else
                            { 
                                introduceOfType = true;
                            } 
                        } 

                        // Get association values from the dependent view 
                        DbExpression qView = ((DbQueryCommandTree)ExternalCalls.CompileView(
                            generatedView.CqlString,
                            storageMappingItemCollection,
                            System.Data.Common.EntitySql.ParserOptions.CompilationMode.RestrictedViewGenerationMode)).Query; 
                        if (introduceOfType)
                        { 
                            qView = qView.OfType(TypeUsage.Create(dependentType)); 
                        }
 
                        if (rc.FromRole.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne)
                        {
                            // Filter out instances with existing relationships.
                            qView = qView.Where(e => 
                            {
                                DbExpression filter = null; 
                                foreach (EdmProperty fkProp in rc.ToProperties) 
                                {
                                    DbExpression notIsNull = e.Property(fkProp).IsNull().Not(); 
                                    filter = null == filter ? notIsNull : filter.And(notIsNull);
                                }
                                return filter;
                            }); 
                        }
                        qView = qView.Select(e => 
                        { 
                            List ends = new List();
                            foreach (AssociationEndMember end in aSet.ElementType.AssociationEndMembers) 
                            {
                                if (end.Name == rc.ToRole.Name)
                                {
                                    var keyValues = new List>(); 
                                    foreach (EdmMember keyMember in dependentSet.ElementType.KeyMembers)
                                    { 
                                        keyValues.Add(e.Property((EdmProperty)keyMember)); 
                                    }
                                    ends.Add(dependentSet.RefFromKey(DbExpressionBuilder.NewRow(keyValues))); 
                                }
                                else
                                {
                                    // Manufacture a key using key values. 
                                    var keyValues = new List>();
                                    foreach (EdmMember keyMember in principalSet.ElementType.KeyMembers) 
                                    { 
                                        int offset = rc.FromProperties.IndexOf((EdmProperty)keyMember);
                                        keyValues.Add(e.Property(rc.ToProperties[offset])); 
                                    }
                                    ends.Add(principalSet.RefFromKey(DbExpressionBuilder.NewRow(keyValues)));
                                }
                            } 
                            return TypeUsage.Create(aSet.ElementType).New(ends);
                        }); 
                        return new GeneratedView(aSet, aSet.ElementType, new DbQueryCommandTree(workspace, DataSpace.SSpace, qView), storageMappingItemCollection, m_config); 
                    }
                } 

                //If no User-defined QV is found, call memoized View Generation procedure
                Dictionary generatedViews = m_generatedViewsMemoizer.Evaluate(extent.EntityContainer);
 
                if (!generatedViews.TryGetValue(extent, out view))
                { 
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.Mapping_Views_For_Extent_Not_Generated( 
                        (extent.EntityContainer.DataSpace==DataSpace.SSpace)?"Table":"EntitySet",extent.Name));
                } 

                return view;
            }
 
            /// 
            /// Collect the views from object collection's view gen assembly 
            ///  
            /// 
            ///  
            private void SerializedCollectViewsFromObjectCollection(MetadataWorkspace workspace, Dictionary extentMappingViews)
            {
                IList allViewGenAssemblies = ObjectItemCollection.ViewGenerationAssemblies;
                if (allViewGenAssemblies != null) 
                {
                    foreach (Assembly assembly in allViewGenAssemblies) 
                    { 
                        object[] viewGenAttributes = assembly.GetCustomAttributes(typeof(System.Data.Mapping.EntityViewGenerationAttribute), false /*inherit*/);
                        if ((viewGenAttributes != null) && (viewGenAttributes.Length != 0)) 
                        {
                            foreach (EntityViewGenerationAttribute viewGenAttribute in viewGenAttributes)
                            {
                                Type viewContainerType = viewGenAttribute.ViewGenerationType; 
                                if (!viewContainerType.IsSubclassOf(typeof(EntityViewContainer)))
                                { 
                                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.Generated_View_Type_Super_Class_1(StorageMslConstructs.EntityViewGenerationTypeName)); 
                                }
                                EntityViewContainer viewContainer = (Activator.CreateInstance(viewContainerType) as EntityViewContainer); 
                                Debug.Assert(viewContainer != null, "Should be able to create the type");

                                if (SerializedAddGeneratedViewsInEntityViewContainer(workspace, viewContainer, extentMappingViews))
                                { 
                                    EntityBid.Trace(" Collected views from Assembly='%ls'\n", assembly.FullName);
                                } 
                            } 
                        }
                    } 
                }
            }

            ///  
            /// this method do the following check on the generated views in the EntityViewContainer,
            /// then add those views all at once to the dicitionary 
            /// 1. there should be one storeageEntityContainerMapping that has the same h 
            ///     C side and S side names as the EnittyViewcontainer
            /// 2. Generate the hash for the storageEntityContainerMapping in the MM closure, 
            ///     and this hash should be the same in EntityViewContainer
            /// 3. Generate the hash for all of the view text in the EntityViewContainer and
            ///     this hash should be the same as the stored on in the EntityViewContainer
            ///  
            /// 
            ///  
            private bool SerializedAddGeneratedViewsInEntityViewContainer(MetadataWorkspace workspace, EntityViewContainer entityViewContainer, Dictionary extentMappingViews) 
            {
                StorageEntityContainerMapping storageEntityContainerMapping; 
                // first check
                if (this.TryGetCorrespondingStorageEntityContainerMapping(entityViewContainer,
                    workspace.GetItemCollection(DataSpace.CSSpace).GetItems(), out storageEntityContainerMapping))
                { 

                    // second check 
                    if (this.SerializedVerifyHashOverMmClosure(storageEntityContainerMapping, entityViewContainer)) 
                    {
                        // third check, prior to the check, we collect all the views in the entity view container to the dictionary 
                        // if the views are changed then we will throw exception out
                        if (this.VerifyViewsHaveNotChanged(workspace, entityViewContainer))
                        {
                            this.SerializedAddGeneratedViews(workspace, entityViewContainer, extentMappingViews); 
                            return true;
                        } 
                        else 
                        {
                            throw new InvalidOperationException(System.Data.Entity.Strings.Generated_Views_Changed); 
                        }
                    }
                    else
                    { 
                        throw new MappingException(Data.Entity.Strings.ViewGen_HashOnMappingClosure_Not_Matching(entityViewContainer.EdmEntityContainerName));
                    } 
                } 
                return false;
 
            }

            private bool TryGetCorrespondingStorageEntityContainerMapping(EntityViewContainer viewContainer,
                IEnumerable storageEntityContainerMappingList, out StorageEntityContainerMapping storageEntityContainerMapping) 
            {
                storageEntityContainerMapping = null; 
 
                foreach (var entityContainerMapping in storageEntityContainerMappingList)
                { 
                    // first check
                    if (entityContainerMapping.EdmEntityContainer.Name == viewContainer.EdmEntityContainerName &&
                        entityContainerMapping.StorageEntityContainer.Name == viewContainer.StoreEntityContainerName)
                    { 
                        storageEntityContainerMapping = entityContainerMapping;
                        return true; 
                    } 
                }
                return false; 

            }

            private bool SerializedVerifyHashOverMmClosure(StorageEntityContainerMapping entityContainerMapping, EntityViewContainer entityViewContainer) 
            {
                if (MetadataMappingHasherVisitor.GetMappingClosureHash(m_storageMappingItemCollection.MappingVersion, entityContainerMapping) == 
                    entityViewContainer.HashOverMappingClosure) 
                {
                    return true; 
                }
                return false;
            }
 
            private bool VerifyViewsHaveNotChanged(MetadataWorkspace workspace, EntityViewContainer viewContainer)
            { 
                //Now check whether the hash of the generated views match the one 
                //we stored in the code file during design
                //Produce the hash and add it to the code 
                string viewHash = MetadataHelper.GenerateHashForAllExtentViewsContent(workspace.SchemaVersion, viewContainer.ExtentViews);
                string storedViewHash = viewContainer.HashOverAllExtentViews;
                if (viewHash != storedViewHash)
                { 
                    return false;
                } 
                return true; 
            }
 

            //Collect the names of the entitysetbases and the generated views from
            //the generated type into a string so that we can produce a hash over it.
            private void SerializedAddGeneratedViews(MetadataWorkspace workspace, EntityViewContainer viewContainer, Dictionary extentMappingViews) 
            {
                foreach (KeyValuePair extentView in viewContainer.ExtentViews) 
                { 
                    EntityContainer entityContainer = null;
                    EntitySetBase extent = null; 


                    string extentFullName = extentView.Key;
                    int extentNameIndex = extentFullName.LastIndexOf('.'); 

                    if (extentNameIndex != -1) 
                    { 
                        string entityContainerName = extentFullName.Substring(0, extentNameIndex);
                        string extentName = extentFullName.Substring(extentFullName.LastIndexOf('.') + 1); 

                        if (!workspace.TryGetItem(entityContainerName, DataSpace.CSpace, out entityContainer))
                        {
                            workspace.TryGetItem(entityContainerName, DataSpace.SSpace, out entityContainer); 
                        }
 
                        if (entityContainer != null) 
                        {
                            entityContainer.BaseEntitySets.TryGetValue(extentName, false, out extent); 
                        }
                    }

                    if (extent == null) 
                    {
                        throw new MappingException(System.Data.Entity.Strings.Generated_Views_Invalid_Extent_1(extentFullName)); 
                    } 

                    //Create a Generated view and cache it 
                    GeneratedView generatedView;
                    //Add the view to the local dictionary
                    if (!extentMappingViews.TryGetValue(extent, out generatedView))
                    { 
                        generatedView = new GeneratedView(extent, null /*edmType*/, extentView.Value, m_storageMappingItemCollection,
                                            new ConfigViewGenerator()); 
                        extentMappingViews.Add(extent, generatedView); 
                    }
                } 
            }


            ///  
            /// Tries to collect the views from the referenced assemblies of Entry assembly.
            ///  
            ///  
            private void SerializedCollectViewsFromReferencedAssemblies(MetadataWorkspace workspace, Dictionary extentMappingViews)
            { 
                ObjectItemCollection objectCollection;
                ItemCollection itemCollection;
                if (!workspace.TryGetItemCollection(DataSpace.OSpace, out itemCollection))
                { 
                    //Possible enhancement : Think about achieving the same thing without creating Object Item Collection.
                    objectCollection = new ObjectItemCollection(); 
                    itemCollection = objectCollection; 
                    // The GetEntryAssembly method can return a null reference
                    //when a managed assembly has been loaded from an unmanaged application. 
                    Assembly entryAssembly = Assembly.GetEntryAssembly();
                    if (entryAssembly != null)
                    {
                        objectCollection.ImplicitLoadViewsFromAllReferencedAssemblies(entryAssembly); 
                    }
                } 
                this.SerializedCollectViewsFromObjectCollection(workspace, extentMappingViews); 
            }
 
            /// 
            /// This method collect all the user defined query views in MSL
            /// Assumption: This method is called only from the StorageMappingItemCollection's constructor
            /// and no other thread can be calling ViewDictionary.GetGeneratedViews() at the same time. 
            /// m_extentMappingViews and m_extentTypeQueryViews are not thread safe.
            ///  
            ///  
            /// 
            internal static void CollectViews(StorageEntityContainerMapping entityContainerMapping, StorageMappingItemCollection storageMappingItemCollection, 
                IList errors, Dictionary userDefinedQueryViewsDict, Dictionary userDefinedQueryViewsOfTypeDict)
            {
                //Create a new MetadataWorkspace, since Query needs it to compile Query
                //Since the MetadataWorkspace really is a thin wrapper over item collections, 
                //this should not pose a problem.
                MetadataWorkspace workspace = new MetadataWorkspace(); 
                workspace.RegisterItemCollection(storageMappingItemCollection.m_edmCollection); 
                workspace.RegisterItemCollection(storageMappingItemCollection.m_storeItemCollection);
                workspace.RegisterItemCollection(storageMappingItemCollection); 
                ConfigViewGenerator config = new ConfigViewGenerator();

                foreach (StorageSetMapping setMapping in entityContainerMapping.AllSetMaps)
                { 
                    if (setMapping.QueryView != null)
                    { 
                        GeneratedView generatedView; 
                        if (!userDefinedQueryViewsDict.TryGetValue(setMapping.Set, out generatedView))
                        { 
                            // Parse the view so that we will get back any errors in the view
                            // Catch the query exception and add it as a parser error
                            try
                            { 
                                //Add first QueryView
                                generatedView = new GeneratedView(setMapping.Set, 
                                                              setMapping.Set.ElementType, setMapping.QueryView.Trim(), storageMappingItemCollection, 
                                                              config);
 
                                bool validationError = false;

                                foreach (EdmSchemaError error in
                                    generatedView.ParseUserSpecifiedView(setMapping, setMapping.Set.ElementType, true /* includeSubtypes*/)) 
                                {
                                    validationError = true; 
                                    errors.Add(error); 
                                }
                                if (!validationError) 
                                {
                                    userDefinedQueryViewsDict.Add(setMapping.Set, generatedView);
                                }
 
                                //Add all type-specific QueryViews
                                foreach (OfTypeQVCacheKey key in setMapping.GetTypeSpecificQVKeys()) 
                                { 
                                    Debug.Assert(key.First.Equals(setMapping.Set));
 
                                    generatedView = new GeneratedView(setMapping.Set,
                                                              key.Second.First /*EntityType*/,
                                                              setMapping.GetTypeSpecificQueryView(key) /*QV*/,
                                                              storageMappingItemCollection, config); 

                                    validationError = false; 
 
                                    foreach (EdmSchemaError error in generatedView.ParseUserSpecifiedView(setMapping, key.Second.First, key.Second.Second))
                                    { 
                                        validationError = true;
                                        errors.Add(error);
                                    }
 
                                    if (!validationError)
                                    { 
                                        userDefinedQueryViewsOfTypeDict.Add(key, generatedView); 
                                    }
 
                                }
                            }
                            catch (Exception e)
                            { 
                                //catching all the exception types since Query parser seems to be throwing veriety of
                                //exceptions - EntityException, ArgumentException, ArgumentNullException etc. 
                                if (EntityUtil.IsCatchableExceptionType(e)) 
                                {
                                    EdmSchemaError error = new EdmSchemaError(System.Data.Entity.Strings.Mapping_Invalid_QueryView_2(setMapping.Set.Name, e.Message), 
                                                               (int)StorageMappingErrorCode.InvalidQueryView, EdmSchemaErrorSeverity.Error,
                                                               setMapping.EntityContainerMapping.SourceLocation, setMapping.StartLineNumber, setMapping.StartLinePosition, e);
                                    errors.Add(error);
                                } 
                                else
                                { 
                                    throw; 
                                }
                            } 
                        }
                    }
                }
            } 
        }
    } 
} 

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

using System.Data.Common.Utils; 
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Data.Common.CommandTrees; 
using System.Data.Metadata.Edm;
using System.Data.Mapping.ViewGeneration; 
using System.Reflection; 
using System.Data.Mapping.Update.Internal;
using System.Linq; 

// All methods prefixed with 'Serialized' have locked access through the shared Memoizer. Do not call it from outside the Memoizer's scope.
namespace System.Data.Mapping
{ 
    using OfTypeQVCacheKey = Pair>;
    using System.Data.Common.CommandTrees.ExpressionBuilder; 
    using System.Data.Mapping.ViewGeneration.Utils; 

    public partial class StorageMappingItemCollection : MappingItemCollection 
    {
        internal delegate bool TryGetUserDefinedQueryView(EntitySetBase extent, out GeneratedView generatedView);
        internal delegate bool TryGetUserDefinedQueryViewOfType(OfTypeQVCacheKey extent, out GeneratedView generatedView);
 
        internal class ViewDictionary
        { 
 
            readonly TryGetUserDefinedQueryView TryGetUserDefinedQueryView;
            readonly TryGetUserDefinedQueryViewOfType TryGetUserDefinedQueryViewOfType; 

            private StorageMappingItemCollection m_storageMappingItemCollection;

            private static ConfigViewGenerator m_config = new ConfigViewGenerator(); 

            // List of assemblies from which we have loaded views from 
            private List m_knownViewGenAssemblies = new List(); 

            // indicates whether the views are being fetched from a generated class or they are being generated at the runtime 
            private bool m_generatedViewsMode = true;

            //Caches computation of view generation (of all EntitySets) for a given EntityContainer
            private readonly Memoizer> m_generatedViewsMemoizer; 

            //Caches computation of getting Type-specific Query Views - either by view gen or user-defined input 
            private readonly Memoizer m_generatedViewOfTypeMemoizer; 

            internal ViewDictionary(StorageMappingItemCollection storageMappingItemCollection, 
                            out Dictionary userDefinedQueryViewsDict,
                            out Dictionary userDefinedQueryViewsOfTypeDict)
            {
                this.m_storageMappingItemCollection = storageMappingItemCollection; 
                this.m_generatedViewsMemoizer = new Memoizer>(SerializedGetGeneratedViews
                    , null); 
                this.m_generatedViewOfTypeMemoizer = new Memoizer(SerializedGeneratedViewOfType, OfTypeQVCacheKey.PairComparer.Instance); 

                userDefinedQueryViewsDict = new Dictionary(EqualityComparer.Default); 
                userDefinedQueryViewsOfTypeDict = new Dictionary(OfTypeQVCacheKey.PairComparer.Instance);

                TryGetUserDefinedQueryView = userDefinedQueryViewsDict.TryGetValue;
                TryGetUserDefinedQueryViewOfType = userDefinedQueryViewsOfTypeDict.TryGetValue; 
            }
 
 
            private Dictionary SerializedGetGeneratedViews(EntityContainer container)
            { 
                Dictionary extentMappingViews = new Dictionary(); ;

                MetadataWorkspace workspace = new MetadataWorkspace();
                workspace.RegisterItemCollection(this.m_storageMappingItemCollection.StoreItemCollection); 
                workspace.RegisterItemCollection(this.m_storageMappingItemCollection.EdmItemCollection);
                workspace.RegisterItemCollection(this.m_storageMappingItemCollection); 
 
                //If we are in generated views mode
                if (m_generatedViewsMode) 
                {
                    if(ObjectItemCollection.ViewGenerationAssemblies!=null && ObjectItemCollection.ViewGenerationAssemblies.Count>0)
                    {
                        SerializedCollectViewsFromObjectCollection(workspace, extentMappingViews); 
                    }
                    else 
                    { 
                        SerializedCollectViewsFromReferencedAssemblies(workspace, extentMappingViews);
                    } 

                    if (this.m_knownViewGenAssemblies.Count != 0)
                    {
                        EntityBid.Trace(" The View generation Mode is Compile Time View Generation\n"); 
                    }
                } 
 
                if (extentMappingViews.Count==0)
                { 
                    //We should change the mode to runtime generation of views.
                    this.m_generatedViewsMode = false;
                    EntityBid.Trace(" The View generation Mode is Runtime View Generation\n");
                    this.SerializedGenerateViews(container, extentMappingViews); 

                } 
 
                Debug.Assert(extentMappingViews.Count>0, "view should be generated at this point");
 
                return extentMappingViews;
            }

            ///  
            /// Call the View Generator's Generate view method
            /// and collect the Views and store it in a local dictionary. 
            ///  
            /// 
            ///  
            private void SerializedGenerateViews(EntityContainer container, Dictionary resultDictionary)
            {
                Debug.Assert(container != null);
 
                //Get the mapping that has the entity container
                //mapped. 
                StorageEntityContainerMapping entityContainerMap = MappingMetadataHelper.GetEntityContainerMap(m_storageMappingItemCollection, container); 
                //If there are no entity set maps, don't call the view generation process
                if (entityContainerMap.IsEmpty) 
                {
                    return;
                }
                ViewGenResults viewGenResults = ViewgenGatekeeper.GenerateViewsFromMapping(entityContainerMap, m_config); 
                KeyToListMap extentMappingViews = viewGenResults.Views;
                if (viewGenResults.HasErrors) 
                { 
                    // Can get the list of errors using viewGenResults.Errors
 
                    throw new MappingException(Helper.CombineErrorMessage(viewGenResults.Errors));
                }

                foreach (KeyValuePair> keyValuePair in extentMappingViews.KeyValuePairs) 
                {
                    //Multiple Views are returned for an extent but the first view 
                    //is the only one that we will use for now. In the future, 
                    //we might start using the other views which are per type within an extent.
                    GeneratedView generatedView; 
                    //Add the view to the local dictionary

                    if (!resultDictionary.TryGetValue(keyValuePair.Key, out generatedView))
                    { 
                        generatedView = keyValuePair.Value[0];
                        resultDictionary.Add(keyValuePair.Key, generatedView); 
                    } 
                }
            } 

            /// 
            /// Generates a single query view for a given Extent and type. It is used to generate OfType and OfTypeOnly views.
            ///  
            /// Whether the view should include extents that are subtypes of the given entity
            private bool TryGenerateQueryViewOfType(EntityContainer entityContainer, EntitySetBase entity, EntityTypeBase type, bool includeSubtypes, out GeneratedView generatedView) 
            { 
                Debug.Assert(entityContainer != null);
                Debug.Assert(entity != null); 
                Debug.Assert(type != null);

                MetadataWorkspace workspace = new MetadataWorkspace();
                workspace.RegisterItemCollection(this.m_storageMappingItemCollection.EdmItemCollection); 
                workspace.RegisterItemCollection(this.m_storageMappingItemCollection.StoreItemCollection);
                workspace.RegisterItemCollection(this.m_storageMappingItemCollection); 
 
                if (type.Abstract)
                { 
                    generatedView = null;
                    return false;
                }
 
                //Get the mapping that has the entity container mapped.
                StorageEntityContainerMapping entityContainerMap = MappingMetadataHelper.GetEntityContainerMap(m_storageMappingItemCollection, entityContainer); 
                Debug.Assert(!entityContainerMap.IsEmpty, "There are no entity set maps"); 

                bool success; 
                ViewGenResults viewGenResults = ViewgenGatekeeper.GenerateTypeSpecificQueryView(entityContainerMap, m_config, entity, type, includeSubtypes, out success);
                if (!success)
                {
                    generatedView = null; 
                    return false; //could not generate view
                } 
 
                KeyToListMap extentMappingViews = viewGenResults.Views;
 
                if (viewGenResults.HasErrors)
                {
                    throw new MappingException(Helper.CombineErrorMessage(viewGenResults.Errors));
                } 

                Debug.Assert(extentMappingViews.AllValues.Count() == 1, "Viewgen should have produced only one view"); 
                generatedView = extentMappingViews.AllValues.First(); 

                return true; 
            }

            /// 
            /// Tries to generate the Oftype or OfTypeOnly query view for a given entity set and type. 
            /// Returns false if the view could not be generated.
            /// Possible reasons for failing are 
            ///   1) Passing in OfTypeOnly on an abstract type 
            ///   2) In user-specified query views mode a query for the given type is absent
            ///  
            internal bool TryGetGeneratedViewOfType(MetadataWorkspace workspace, EntitySetBase entity, EntityTypeBase type, bool includeSubtypes, out GeneratedView generatedView)
            {
                OfTypeQVCacheKey key = new OfTypeQVCacheKey(entity, new Pair(type, includeSubtypes));
                generatedView = this.m_generatedViewOfTypeMemoizer.Evaluate(key); 
                return (generatedView != null);
            } 
 
            /// 
            /// Note: Null return value implies QV was not generated. 
            /// 
            /// 
            private GeneratedView SerializedGeneratedViewOfType(OfTypeQVCacheKey arg)
            { 
                GeneratedView generatedView;
                //See if we have collected user-defined QueryView 
                if(TryGetUserDefinedQueryViewOfType(arg, out generatedView)) 
                {
                    return generatedView; 
                }

                //Now we have to generate the type-specific view
                EntitySetBase entity = arg.First; 
                EntityTypeBase type = arg.Second.First;
                bool includeSubtypes = arg.Second.Second; 
 
                if (!TryGenerateQueryViewOfType(entity.EntityContainer, entity, type, includeSubtypes, out generatedView))
                { 
                    generatedView = null;
                }

                return generatedView; 
            }
 
            ///  
            /// Returns the update or query view for an Extent as a
            /// string. 
            /// There are a series of steps that we go through for discovering a view for an extent.
            /// To start with we assume that we are working with Generated Views. To find out the
            /// generated view we go to the ObjectItemCollection and see if it is not-null. If the ObjectItemCollection
            /// is non-null, we get the view generation assemblies that it might have cached during the 
            /// Object metadata discovery.If there are no view generation assemblies we switch to the
            /// runtime view generation strategy. If there are view generation assemblies, we get the list and 
            /// go through them and see if there are any assemblies that are there from which we have not already loaded 
            /// the views. We collect the views from assemblies that we have not already collected from earlier.
            /// If the ObjectItemCollection is null and we are in the view generation mode, that means that 
            /// the query or update is issued from the Value layer and this is the first time view has been asked for.
            /// The compile time view gen for value layer queries will work for very simple scenarios.
            /// If the users wants to get the performance benefit, they should call MetadataWorkspace.LoadFromAssembly.
            /// At this point we go through the referenced assemblies of the entry assembly( this wont work for Asp.net 
            /// or if the viewgen assembly was not referenced by the executing application).
            /// and try to see if there were any view gen assemblies. If there are, we collect the views for all extents. 
            /// Once we have all the generated views gathered, we try to get the view for the extent passed in. 
            /// If we find one we will return it. If we can't find one an exception will be thrown.
            /// If there were no view gen assemblies either in the ObjectItemCollection or in the list of referenced 
            /// assemblies of calling assembly, we change the mode to runtime view generation and will continue to
            /// be in that mode for the rest of the lifetime of the mapping item collection.
            /// 
            internal GeneratedView GetGeneratedView(EntitySetBase extent, MetadataWorkspace workspace, StorageMappingItemCollection storageMappingItemCollection) 
            {
                //First check if we have collected a view from user-defined query views 
                //Dont need to worry whether to generate Query view or update viw, because that is relative to the extent. 
                GeneratedView view;
 
                if (TryGetUserDefinedQueryView(extent, out view))
                {
                    return view;
                } 

                //If this is a foreign key association, manufacture a view on the fly. 
                if (extent.BuiltInTypeKind == BuiltInTypeKind.AssociationSet) 
                {
                    AssociationSet aSet = (AssociationSet)extent; 
                    if (aSet.ElementType.IsForeignKey)
                    {
                        // Although we expose a collection of constraints in the API, there is only ever one
                        // constraint. 
                        ReferentialConstraint rc = aSet.ElementType.ReferentialConstraints.Single();
                        EntitySet dependentSet = aSet.AssociationSetEnds[rc.ToRole.Name].EntitySet; 
                        EntitySet principalSet = aSet.AssociationSetEnds[rc.FromRole.Name].EntitySet; 

                        // Introduce an OfType view if the dependent end is a subtype of the entity set 
                        EntityType dependentType = MetadataHelper.GetEntityTypeForEnd((AssociationEndMember)rc.ToRole);
                        GeneratedView generatedView = GetGeneratedView(dependentSet, workspace, storageMappingItemCollection);
                        bool introduceOfType = false;
                        if (dependentSet.ElementType.IsBaseTypeOf(dependentType)) 
                        {
                            // First check for an OfType view 
                            GeneratedView ofTypeGeneratedView; 
                            if (TryGetGeneratedViewOfType(workspace, dependentSet, dependentType, true, out ofTypeGeneratedView))
                            { 
                                generatedView = ofTypeGeneratedView;
                            }
                            else
                            { 
                                introduceOfType = true;
                            } 
                        } 

                        // Get association values from the dependent view 
                        DbExpression qView = ((DbQueryCommandTree)ExternalCalls.CompileView(
                            generatedView.CqlString,
                            storageMappingItemCollection,
                            System.Data.Common.EntitySql.ParserOptions.CompilationMode.RestrictedViewGenerationMode)).Query; 
                        if (introduceOfType)
                        { 
                            qView = qView.OfType(TypeUsage.Create(dependentType)); 
                        }
 
                        if (rc.FromRole.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne)
                        {
                            // Filter out instances with existing relationships.
                            qView = qView.Where(e => 
                            {
                                DbExpression filter = null; 
                                foreach (EdmProperty fkProp in rc.ToProperties) 
                                {
                                    DbExpression notIsNull = e.Property(fkProp).IsNull().Not(); 
                                    filter = null == filter ? notIsNull : filter.And(notIsNull);
                                }
                                return filter;
                            }); 
                        }
                        qView = qView.Select(e => 
                        { 
                            List ends = new List();
                            foreach (AssociationEndMember end in aSet.ElementType.AssociationEndMembers) 
                            {
                                if (end.Name == rc.ToRole.Name)
                                {
                                    var keyValues = new List>(); 
                                    foreach (EdmMember keyMember in dependentSet.ElementType.KeyMembers)
                                    { 
                                        keyValues.Add(e.Property((EdmProperty)keyMember)); 
                                    }
                                    ends.Add(dependentSet.RefFromKey(DbExpressionBuilder.NewRow(keyValues))); 
                                }
                                else
                                {
                                    // Manufacture a key using key values. 
                                    var keyValues = new List>();
                                    foreach (EdmMember keyMember in principalSet.ElementType.KeyMembers) 
                                    { 
                                        int offset = rc.FromProperties.IndexOf((EdmProperty)keyMember);
                                        keyValues.Add(e.Property(rc.ToProperties[offset])); 
                                    }
                                    ends.Add(principalSet.RefFromKey(DbExpressionBuilder.NewRow(keyValues)));
                                }
                            } 
                            return TypeUsage.Create(aSet.ElementType).New(ends);
                        }); 
                        return new GeneratedView(aSet, aSet.ElementType, new DbQueryCommandTree(workspace, DataSpace.SSpace, qView), storageMappingItemCollection, m_config); 
                    }
                } 

                //If no User-defined QV is found, call memoized View Generation procedure
                Dictionary generatedViews = m_generatedViewsMemoizer.Evaluate(extent.EntityContainer);
 
                if (!generatedViews.TryGetValue(extent, out view))
                { 
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.Mapping_Views_For_Extent_Not_Generated( 
                        (extent.EntityContainer.DataSpace==DataSpace.SSpace)?"Table":"EntitySet",extent.Name));
                } 

                return view;
            }
 
            /// 
            /// Collect the views from object collection's view gen assembly 
            ///  
            /// 
            ///  
            private void SerializedCollectViewsFromObjectCollection(MetadataWorkspace workspace, Dictionary extentMappingViews)
            {
                IList allViewGenAssemblies = ObjectItemCollection.ViewGenerationAssemblies;
                if (allViewGenAssemblies != null) 
                {
                    foreach (Assembly assembly in allViewGenAssemblies) 
                    { 
                        object[] viewGenAttributes = assembly.GetCustomAttributes(typeof(System.Data.Mapping.EntityViewGenerationAttribute), false /*inherit*/);
                        if ((viewGenAttributes != null) && (viewGenAttributes.Length != 0)) 
                        {
                            foreach (EntityViewGenerationAttribute viewGenAttribute in viewGenAttributes)
                            {
                                Type viewContainerType = viewGenAttribute.ViewGenerationType; 
                                if (!viewContainerType.IsSubclassOf(typeof(EntityViewContainer)))
                                { 
                                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.Generated_View_Type_Super_Class_1(StorageMslConstructs.EntityViewGenerationTypeName)); 
                                }
                                EntityViewContainer viewContainer = (Activator.CreateInstance(viewContainerType) as EntityViewContainer); 
                                Debug.Assert(viewContainer != null, "Should be able to create the type");

                                if (SerializedAddGeneratedViewsInEntityViewContainer(workspace, viewContainer, extentMappingViews))
                                { 
                                    EntityBid.Trace(" Collected views from Assembly='%ls'\n", assembly.FullName);
                                } 
                            } 
                        }
                    } 
                }
            }

            ///  
            /// this method do the following check on the generated views in the EntityViewContainer,
            /// then add those views all at once to the dicitionary 
            /// 1. there should be one storeageEntityContainerMapping that has the same h 
            ///     C side and S side names as the EnittyViewcontainer
            /// 2. Generate the hash for the storageEntityContainerMapping in the MM closure, 
            ///     and this hash should be the same in EntityViewContainer
            /// 3. Generate the hash for all of the view text in the EntityViewContainer and
            ///     this hash should be the same as the stored on in the EntityViewContainer
            ///  
            /// 
            ///  
            private bool SerializedAddGeneratedViewsInEntityViewContainer(MetadataWorkspace workspace, EntityViewContainer entityViewContainer, Dictionary extentMappingViews) 
            {
                StorageEntityContainerMapping storageEntityContainerMapping; 
                // first check
                if (this.TryGetCorrespondingStorageEntityContainerMapping(entityViewContainer,
                    workspace.GetItemCollection(DataSpace.CSSpace).GetItems(), out storageEntityContainerMapping))
                { 

                    // second check 
                    if (this.SerializedVerifyHashOverMmClosure(storageEntityContainerMapping, entityViewContainer)) 
                    {
                        // third check, prior to the check, we collect all the views in the entity view container to the dictionary 
                        // if the views are changed then we will throw exception out
                        if (this.VerifyViewsHaveNotChanged(workspace, entityViewContainer))
                        {
                            this.SerializedAddGeneratedViews(workspace, entityViewContainer, extentMappingViews); 
                            return true;
                        } 
                        else 
                        {
                            throw new InvalidOperationException(System.Data.Entity.Strings.Generated_Views_Changed); 
                        }
                    }
                    else
                    { 
                        throw new MappingException(Data.Entity.Strings.ViewGen_HashOnMappingClosure_Not_Matching(entityViewContainer.EdmEntityContainerName));
                    } 
                } 
                return false;
 
            }

            private bool TryGetCorrespondingStorageEntityContainerMapping(EntityViewContainer viewContainer,
                IEnumerable storageEntityContainerMappingList, out StorageEntityContainerMapping storageEntityContainerMapping) 
            {
                storageEntityContainerMapping = null; 
 
                foreach (var entityContainerMapping in storageEntityContainerMappingList)
                { 
                    // first check
                    if (entityContainerMapping.EdmEntityContainer.Name == viewContainer.EdmEntityContainerName &&
                        entityContainerMapping.StorageEntityContainer.Name == viewContainer.StoreEntityContainerName)
                    { 
                        storageEntityContainerMapping = entityContainerMapping;
                        return true; 
                    } 
                }
                return false; 

            }

            private bool SerializedVerifyHashOverMmClosure(StorageEntityContainerMapping entityContainerMapping, EntityViewContainer entityViewContainer) 
            {
                if (MetadataMappingHasherVisitor.GetMappingClosureHash(m_storageMappingItemCollection.MappingVersion, entityContainerMapping) == 
                    entityViewContainer.HashOverMappingClosure) 
                {
                    return true; 
                }
                return false;
            }
 
            private bool VerifyViewsHaveNotChanged(MetadataWorkspace workspace, EntityViewContainer viewContainer)
            { 
                //Now check whether the hash of the generated views match the one 
                //we stored in the code file during design
                //Produce the hash and add it to the code 
                string viewHash = MetadataHelper.GenerateHashForAllExtentViewsContent(workspace.SchemaVersion, viewContainer.ExtentViews);
                string storedViewHash = viewContainer.HashOverAllExtentViews;
                if (viewHash != storedViewHash)
                { 
                    return false;
                } 
                return true; 
            }
 

            //Collect the names of the entitysetbases and the generated views from
            //the generated type into a string so that we can produce a hash over it.
            private void SerializedAddGeneratedViews(MetadataWorkspace workspace, EntityViewContainer viewContainer, Dictionary extentMappingViews) 
            {
                foreach (KeyValuePair extentView in viewContainer.ExtentViews) 
                { 
                    EntityContainer entityContainer = null;
                    EntitySetBase extent = null; 


                    string extentFullName = extentView.Key;
                    int extentNameIndex = extentFullName.LastIndexOf('.'); 

                    if (extentNameIndex != -1) 
                    { 
                        string entityContainerName = extentFullName.Substring(0, extentNameIndex);
                        string extentName = extentFullName.Substring(extentFullName.LastIndexOf('.') + 1); 

                        if (!workspace.TryGetItem(entityContainerName, DataSpace.CSpace, out entityContainer))
                        {
                            workspace.TryGetItem(entityContainerName, DataSpace.SSpace, out entityContainer); 
                        }
 
                        if (entityContainer != null) 
                        {
                            entityContainer.BaseEntitySets.TryGetValue(extentName, false, out extent); 
                        }
                    }

                    if (extent == null) 
                    {
                        throw new MappingException(System.Data.Entity.Strings.Generated_Views_Invalid_Extent_1(extentFullName)); 
                    } 

                    //Create a Generated view and cache it 
                    GeneratedView generatedView;
                    //Add the view to the local dictionary
                    if (!extentMappingViews.TryGetValue(extent, out generatedView))
                    { 
                        generatedView = new GeneratedView(extent, null /*edmType*/, extentView.Value, m_storageMappingItemCollection,
                                            new ConfigViewGenerator()); 
                        extentMappingViews.Add(extent, generatedView); 
                    }
                } 
            }


            ///  
            /// Tries to collect the views from the referenced assemblies of Entry assembly.
            ///  
            ///  
            private void SerializedCollectViewsFromReferencedAssemblies(MetadataWorkspace workspace, Dictionary extentMappingViews)
            { 
                ObjectItemCollection objectCollection;
                ItemCollection itemCollection;
                if (!workspace.TryGetItemCollection(DataSpace.OSpace, out itemCollection))
                { 
                    //Possible enhancement : Think about achieving the same thing without creating Object Item Collection.
                    objectCollection = new ObjectItemCollection(); 
                    itemCollection = objectCollection; 
                    // The GetEntryAssembly method can return a null reference
                    //when a managed assembly has been loaded from an unmanaged application. 
                    Assembly entryAssembly = Assembly.GetEntryAssembly();
                    if (entryAssembly != null)
                    {
                        objectCollection.ImplicitLoadViewsFromAllReferencedAssemblies(entryAssembly); 
                    }
                } 
                this.SerializedCollectViewsFromObjectCollection(workspace, extentMappingViews); 
            }
 
            /// 
            /// This method collect all the user defined query views in MSL
            /// Assumption: This method is called only from the StorageMappingItemCollection's constructor
            /// and no other thread can be calling ViewDictionary.GetGeneratedViews() at the same time. 
            /// m_extentMappingViews and m_extentTypeQueryViews are not thread safe.
            ///  
            ///  
            /// 
            internal static void CollectViews(StorageEntityContainerMapping entityContainerMapping, StorageMappingItemCollection storageMappingItemCollection, 
                IList errors, Dictionary userDefinedQueryViewsDict, Dictionary userDefinedQueryViewsOfTypeDict)
            {
                //Create a new MetadataWorkspace, since Query needs it to compile Query
                //Since the MetadataWorkspace really is a thin wrapper over item collections, 
                //this should not pose a problem.
                MetadataWorkspace workspace = new MetadataWorkspace(); 
                workspace.RegisterItemCollection(storageMappingItemCollection.m_edmCollection); 
                workspace.RegisterItemCollection(storageMappingItemCollection.m_storeItemCollection);
                workspace.RegisterItemCollection(storageMappingItemCollection); 
                ConfigViewGenerator config = new ConfigViewGenerator();

                foreach (StorageSetMapping setMapping in entityContainerMapping.AllSetMaps)
                { 
                    if (setMapping.QueryView != null)
                    { 
                        GeneratedView generatedView; 
                        if (!userDefinedQueryViewsDict.TryGetValue(setMapping.Set, out generatedView))
                        { 
                            // Parse the view so that we will get back any errors in the view
                            // Catch the query exception and add it as a parser error
                            try
                            { 
                                //Add first QueryView
                                generatedView = new GeneratedView(setMapping.Set, 
                                                              setMapping.Set.ElementType, setMapping.QueryView.Trim(), storageMappingItemCollection, 
                                                              config);
 
                                bool validationError = false;

                                foreach (EdmSchemaError error in
                                    generatedView.ParseUserSpecifiedView(setMapping, setMapping.Set.ElementType, true /* includeSubtypes*/)) 
                                {
                                    validationError = true; 
                                    errors.Add(error); 
                                }
                                if (!validationError) 
                                {
                                    userDefinedQueryViewsDict.Add(setMapping.Set, generatedView);
                                }
 
                                //Add all type-specific QueryViews
                                foreach (OfTypeQVCacheKey key in setMapping.GetTypeSpecificQVKeys()) 
                                { 
                                    Debug.Assert(key.First.Equals(setMapping.Set));
 
                                    generatedView = new GeneratedView(setMapping.Set,
                                                              key.Second.First /*EntityType*/,
                                                              setMapping.GetTypeSpecificQueryView(key) /*QV*/,
                                                              storageMappingItemCollection, config); 

                                    validationError = false; 
 
                                    foreach (EdmSchemaError error in generatedView.ParseUserSpecifiedView(setMapping, key.Second.First, key.Second.Second))
                                    { 
                                        validationError = true;
                                        errors.Add(error);
                                    }
 
                                    if (!validationError)
                                    { 
                                        userDefinedQueryViewsOfTypeDict.Add(key, generatedView); 
                                    }
 
                                }
                            }
                            catch (Exception e)
                            { 
                                //catching all the exception types since Query parser seems to be throwing veriety of
                                //exceptions - EntityException, ArgumentException, ArgumentNullException etc. 
                                if (EntityUtil.IsCatchableExceptionType(e)) 
                                {
                                    EdmSchemaError error = new EdmSchemaError(System.Data.Entity.Strings.Mapping_Invalid_QueryView_2(setMapping.Set.Name, e.Message), 
                                                               (int)StorageMappingErrorCode.InvalidQueryView, EdmSchemaErrorSeverity.Error,
                                                               setMapping.EntityContainerMapping.SourceLocation, setMapping.StartLineNumber, setMapping.StartLinePosition, e);
                                    errors.Add(error);
                                } 
                                else
                                { 
                                    throw; 
                                }
                            } 
                        }
                    }
                }
            } 
        }
    } 
} 

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