ViewLoader.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 / Map / Update / Internal / ViewLoader.cs / 2 / ViewLoader.cs

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

using System.Data.Common.CommandTrees; 
using System.Data.Metadata.Edm;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Common.CommandTrees.Internal; 
using System.Data.Common.Utils;
using System.Diagnostics; 
using System.Data.Common; 
using System.Data.Objects;
using System.Linq; 
using System.Threading;
namespace System.Data.Mapping.Update.Internal
{
    ///  
    /// Retrieves update mapping views and dependency information for update mapping views. Acts as a wrapper around
    /// the metadata workspace (and allows direct definition of update mapping views for test purposes). 
    ///  
    internal class ViewLoader
    { 
        #region Constructors
        /// 
        /// Constructor specifying a metadata workspace to use for mapping views.
        ///  
        /// mapping item collection used for retrieving updating mapping views.
        internal ViewLoader(StorageMappingItemCollection mappingItemCollection) 
        { 
            Debug.Assert(mappingItemCollection != null);
            m_mappingItemCollection = mappingItemCollection; 
        }
        #endregion

        #region Fields 
        private readonly Dictionary m_associationSetMetadata = new Dictionary();
        private readonly Dictionary> m_affectedTables = new Dictionary>(); 
        private readonly Set m_serverGenProperties = new Set(); 
        private readonly Set m_isNullConditionProperties = new Set();
        private readonly StorageMappingItemCollection m_mappingItemCollection; 
        private readonly Dictionary m_functionMappingTranslators = new Dictionary(
            EqualityComparer.Default);
        private readonly ReaderWriterLockSlim m_readerWriterLock = new ReaderWriterLockSlim();
        #endregion 

        #region Methods 
        ///  
        /// For a given extent, returns the function mapping translator.
        ///  
        /// Association set or entity set for which to retrieve a translator
        /// Function translator or null if none exists for this extent
        internal FunctionMappingTranslator GetFunctionMappingTranslator(EntitySetBase extent)
        { 
            return SyncGetValue(m_functionMappingTranslators, extent);
        } 
 
        /// 
        /// Returns store tables affected by modifications to a particular C-layer extent. Although this 
        /// information can be inferred from the update view, we want to avoid compiling or loading
        /// views when not required. This information can be directly determined from mapping metadata.
        /// 
        /// C-layer extent. 
        /// Affected store tables.
        internal Set GetAffectedTables(EntitySetBase extent) 
        { 
            return SyncGetValue(m_affectedTables, extent);
        } 

        /// 
        /// Gets information relevant to the processing of an AssociationSet in the update pipeline.
        /// Caches information on first retrieval. 
        /// 
        internal AssociationSetMetadata GetAssociationSetMetadata(AssociationSet associationSet) 
        { 
            return SyncGetValue(m_associationSetMetadata, associationSet);
        } 

        /// 
        /// Determines whether the given member maps to a server-generated column in the store.
        /// Requires: InitializeExtentInformation has been called for the extent being persisted. 
        /// 
        /// Member to lookup 
        /// Whether the member is server generated in some context 
        internal bool IsServerGen(EdmMember member)
        { 
            return SyncContains(m_serverGenProperties, member);
        }

        ///  
        /// Determines whether the given member maps to a column participating in an isnull
        /// condition. Useful to determine if a nullability constraint violation is going to 
        /// cause roundtripping problems (e.g. if type is based on nullability of a 'non-nullable' 
        /// property of a derived entity type)
        ///  
        internal bool IsNullConditionMember(EdmMember member)
        {
            return SyncContains(m_isNullConditionProperties, member);
        } 

        ///  
        /// Utility method reading value from dictionary within read lock. 
        /// 
        private T_Value SyncGetValue(Dictionary dictionary, T_Key key) 
        {
            m_readerWriterLock.EnterReadLock();
            try
            { 
                return dictionary[key];
            } 
            finally 
            {
                m_readerWriterLock.ExitReadLock(); 
            }
        }

        ///  
        /// Utility method checking for membership of element in set within read lock.
        ///  
        private bool SyncContains(Set set, T_Element element) 
        {
            m_readerWriterLock.EnterReadLock(); 
            try
            {
                return set.Contains(element);
            } 
            finally
            { 
                m_readerWriterLock.ExitReadLock(); 
            }
        } 

        /// 
        /// Initializes all information relevant to the entity set.
        ///  
        /// Association set or entity set to load.
        /// metadata workspace 
        internal void SyncInitializeEntitySet(EntitySetBase entitySetBase, MetadataWorkspace workspace) 
        {
            m_readerWriterLock.EnterReadLock(); 
            try
            {
                // check if we've already done the work for this entity set
                if (m_affectedTables.ContainsKey(entitySetBase)) 
                {
                    return; 
                } 
            }
            finally 
            {
                m_readerWriterLock.ExitReadLock();
            }
 
            // acquire a write lock
            m_readerWriterLock.EnterWriteLock(); 
            try 
            {
                // see if we've since done the work for this entity set 
                if (m_affectedTables.ContainsKey(entitySetBase))
                {
                    return;
                } 

                InitializeEntitySet(entitySetBase, workspace); 
            } 
            finally
            { 
                m_readerWriterLock.ExitWriteLock();
            }
        }
 
        private void InitializeEntitySet(EntitySetBase entitySetBase, MetadataWorkspace workspace)
        { 
            // make sure views have been generated for this sub-graph (trigger generation of the sub-graph 
            // by retrieving a view for one of its components; not actually using the view here)
            m_mappingItemCollection.GetGeneratedView(entitySetBase, workspace); 
            Set affectedTables = new Set();

            StorageEntityContainerMapping mapping = (StorageEntityContainerMapping)m_mappingItemCollection.GetMap(entitySetBase.EntityContainer);
 
            if (null != mapping)
            { 
                Set isNullConditionColumns = new Set(); 

                // find extent in the container mapping 
                StorageSetMapping setMapping;
                if (entitySetBase.BuiltInTypeKind == BuiltInTypeKind.EntitySet)
                {
                    setMapping = mapping.GetEntitySetMapping(entitySetBase.Name); 

                    // Check for members that have result bindings in a function mapping. If a 
                    // function returns the member values, it indicates they are server-generated 
                    m_serverGenProperties.Unite(GetMembersWithResultBinding((StorageEntitySetMapping)setMapping));
                } 
                else if (entitySetBase.BuiltInTypeKind == BuiltInTypeKind.AssociationSet)
                {
                    setMapping = mapping.GetRelationshipSetMapping(entitySetBase.Name);
                } 
                else
                { 
                    Debug.Fail("unexpected extent type " + entitySetBase.BuiltInTypeKind); 
                    throw EntityUtil.NotSupported();
                } 

                // gather interesting tables, columns and properties from mapping fragments
                foreach (StorageMappingFragment mappingFragment in GetMappingFragments(setMapping))
                { 
                    affectedTables.Add(mappingFragment.TableSet);
 
                    // get all property mappings to figure out if anything is server generated 
                    m_serverGenProperties.AddRange(FindServerGenMembers(mappingFragment));
 
                    // get all columns participating in is null conditions
                    isNullConditionColumns.AddRange(FindIsNullConditionColumns(mappingFragment));
                }
 
                if (0 < isNullConditionColumns.Count)
                { 
                    // gather is null condition properties based on is null condition columns 
                    foreach (StorageMappingFragment mappingFragment in GetMappingFragments(setMapping))
                    { 
                        m_isNullConditionProperties.AddRange(FindPropertiesMappedToColumns(isNullConditionColumns, mappingFragment));
                    }
                }
            } 

            m_affectedTables.Add(entitySetBase, affectedTables.MakeReadOnly()); 
 
            InitializeFunctionMappingTranslators(entitySetBase, mapping);
 
            // for association sets, initialize AssociationSetMetadata if no function has claimed ownership
            // of the association yet
            if (entitySetBase.BuiltInTypeKind == BuiltInTypeKind.AssociationSet)
            { 
                AssociationSet associationSet = (AssociationSet)entitySetBase;
                if (!m_associationSetMetadata.ContainsKey(associationSet)) 
                { 
                    m_associationSetMetadata.Add(associationSet, new AssociationSetMetadata(
                        m_affectedTables[associationSet], associationSet, workspace)); 
                }
            }
        }
 
        /// 
        /// Yields all members appearing in function mapping result bindings. 
        ///  
        /// Set mapping to examine
        /// All result bindings 
        private IEnumerable GetMembersWithResultBinding(StorageEntitySetMapping entitySetMapping)
        {
            foreach (StorageEntityTypeFunctionMapping typeFunctionMapping in entitySetMapping.FunctionMappings)
            { 
                // look at all result bindings for insert and update commands
                if (null != typeFunctionMapping.InsertFunctionMapping.ResultBindings) 
                { 
                    foreach (StorageFunctionResultBinding binding in typeFunctionMapping.InsertFunctionMapping.ResultBindings)
                    { 
                        yield return binding.Property;
                    }
                }
                if (null != typeFunctionMapping.UpdateFunctionMapping.ResultBindings) 
                {
                    foreach (StorageFunctionResultBinding binding in typeFunctionMapping.UpdateFunctionMapping.ResultBindings) 
                    { 
                        yield return binding.Property;
                    } 
                }
            }
        }
 
        // Loads and registers any function mapping translators for the given extent (and related container)
        private void InitializeFunctionMappingTranslators(EntitySetBase entitySetBase, StorageEntityContainerMapping mapping) 
        { 
            KeyToListMap requiredEnds = new KeyToListMap(
                EqualityComparer.Default); 

            // see if function mapping metadata needs to be processed
            if (!m_functionMappingTranslators.ContainsKey(entitySetBase))
            { 
                // load all function mapping data from the current entity container
                foreach (StorageEntitySetMapping entitySetMapping in mapping.EntitySetMaps) 
                { 
                    if (0 < entitySetMapping.FunctionMappings.Count)
                    { 
                        // register the function mapping
                        m_functionMappingTranslators.Add(entitySetMapping.Set, FunctionMappingTranslator.CreateEntitySetFunctionMappingTranslator(entitySetMapping));

                        // register "null" function translators for all implicitly mapped association sets 
                        foreach (AssociationSetEnd end in entitySetMapping.ImplicitlyMappedAssociationSetEnds)
                        { 
                            AssociationSet associationSet = end.ParentAssociationSet; 
                            if (!m_functionMappingTranslators.ContainsKey(associationSet))
                            { 
                                m_functionMappingTranslators.Add(associationSet, FunctionMappingTranslator.CreateAssociationSetFunctionMappingTranslator(null));
                            }

                            // Remember that the current entity set is required for all updates to the collocated 
                            // relationship set. This entity set's end is opposite the target end for the mapping.
                            AssociationSetEnd oppositeEnd = MetadataHelper.GetOppositeEnd(end); 
                            requiredEnds.Add(associationSet, oppositeEnd.CorrespondingAssociationEndMember); 
                        }
                    } 
                    else
                    {
                        // register null translator (so that we never attempt to process this extent again)
                        m_functionMappingTranslators.Add(entitySetMapping.Set, null); 
                    }
                } 
 
                foreach (StorageAssociationSetMapping associationSetMapping in mapping.RelationshipSetMaps)
                { 
                    if (null != associationSetMapping.FunctionMapping)
                    {
                        AssociationSet set = (AssociationSet)associationSetMapping.Set;
 
                        // use indexer rather than Add since the association set may already have an implicit function
                        // mapping -- this explicit function mapping takes precedence in such cases 
                        m_functionMappingTranslators.Add(set, 
                            FunctionMappingTranslator.CreateAssociationSetFunctionMappingTranslator(associationSetMapping));
 
                        // remember that we've seen a function mapping for this association set, which overrides
                        // any other behaviors for determining required/optional ends
                        requiredEnds.AddRange(set, Enumerable.Empty());
                    } 
                    else
                    { 
                        if (!m_functionMappingTranslators.ContainsKey(associationSetMapping.Set)) 
                        {
                            // register null translator (so that we never attempt to process this extent again) 
                            m_functionMappingTranslators.Add(associationSetMapping.Set, null);
                        }
                    }
                } 
            }
 
            // register association metadata for all association sets encountered 
            foreach (AssociationSet associationSet in requiredEnds.Keys)
            { 
                m_associationSetMetadata.Add(associationSet, new AssociationSetMetadata(
                    requiredEnds.EnumerateValues(associationSet)));
            }
        } 

        ///  
        /// Gets all model properties mapped to server generated columns. 
        /// 
        private static IEnumerable FindServerGenMembers(StorageMappingFragment mappingFragment) 
        {
            foreach (var scalarPropertyMapping in FlattenPropertyMappings(mappingFragment.AllProperties)
                .OfType())
            { 
                if (StoreGeneratedPattern.None != MetadataHelper.GetStoreGeneratedPattern(scalarPropertyMapping.ColumnProperty))
                { 
                    yield return scalarPropertyMapping.EdmProperty; 
                }
            } 
        }

        /// 
        /// Gets all store columns participating in is null conditions. 
        /// 
        private static IEnumerable FindIsNullConditionColumns(StorageMappingFragment mappingFragment) 
        { 
            foreach (var conditionPropertyMapping in FlattenPropertyMappings(mappingFragment.AllProperties)
                .OfType()) 
            {
                if (conditionPropertyMapping.ColumnProperty != null &&
                    conditionPropertyMapping.IsNull.HasValue)
                { 
                    yield return conditionPropertyMapping.ColumnProperty;
                } 
            } 
        }
 
        /// 
        /// Gets all model properties mapped to given columns.
        /// 
        private static IEnumerable FindPropertiesMappedToColumns(Set columns, StorageMappingFragment mappingFragment) 
        {
            foreach (var scalarPropertyMapping in FlattenPropertyMappings(mappingFragment.AllProperties) 
                .OfType()) 
            {
                if (columns.Contains(scalarPropertyMapping.ColumnProperty)) 
                {
                    yield return scalarPropertyMapping.EdmProperty;
                }
            } 
        }
 
        ///  
        /// Enumerates all mapping fragments in given set mapping.
        ///  
        private static IEnumerable GetMappingFragments(StorageSetMapping setMapping)
        {
            // get all type mappings for the extent
            foreach (StorageTypeMapping typeMapping in setMapping.TypeMappings) 
            {
                // get all table mapping fragments for the type 
                foreach (StorageMappingFragment mappingFragment in typeMapping.MappingFragments) 
                {
                    yield return mappingFragment; 
                }
            }
        }
 
        /// 
        /// Returns all bottom-level mappings (e.g. conditions and scalar property mappings but not complex property mappings 
        /// whose components are returned) 
        /// 
        private static IEnumerable FlattenPropertyMappings(System.Collections.ObjectModel.ReadOnlyCollection propertyMappings) 
        {
            foreach (StoragePropertyMapping propertyMapping in propertyMappings)
            {
                StorageComplexPropertyMapping complexPropertyMapping = propertyMapping as StorageComplexPropertyMapping; 
                if (null != complexPropertyMapping)
                { 
                    foreach (StorageComplexTypeMapping complexTypeMapping in complexPropertyMapping.TypeMappings) 
                    {
                        // recursively call self with nested type 
                        foreach (StoragePropertyMapping nestedPropertyMapping in FlattenPropertyMappings(complexTypeMapping.AllProperties))
                        {
                            yield return nestedPropertyMapping;
                        } 
                    }
                } 
                else 
                {
                    yield return propertyMapping; 
                }
            }
        }
        #endregion 
    }
} 

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

using System.Data.Common.CommandTrees; 
using System.Data.Metadata.Edm;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Common.CommandTrees.Internal; 
using System.Data.Common.Utils;
using System.Diagnostics; 
using System.Data.Common; 
using System.Data.Objects;
using System.Linq; 
using System.Threading;
namespace System.Data.Mapping.Update.Internal
{
    ///  
    /// Retrieves update mapping views and dependency information for update mapping views. Acts as a wrapper around
    /// the metadata workspace (and allows direct definition of update mapping views for test purposes). 
    ///  
    internal class ViewLoader
    { 
        #region Constructors
        /// 
        /// Constructor specifying a metadata workspace to use for mapping views.
        ///  
        /// mapping item collection used for retrieving updating mapping views.
        internal ViewLoader(StorageMappingItemCollection mappingItemCollection) 
        { 
            Debug.Assert(mappingItemCollection != null);
            m_mappingItemCollection = mappingItemCollection; 
        }
        #endregion

        #region Fields 
        private readonly Dictionary m_associationSetMetadata = new Dictionary();
        private readonly Dictionary> m_affectedTables = new Dictionary>(); 
        private readonly Set m_serverGenProperties = new Set(); 
        private readonly Set m_isNullConditionProperties = new Set();
        private readonly StorageMappingItemCollection m_mappingItemCollection; 
        private readonly Dictionary m_functionMappingTranslators = new Dictionary(
            EqualityComparer.Default);
        private readonly ReaderWriterLockSlim m_readerWriterLock = new ReaderWriterLockSlim();
        #endregion 

        #region Methods 
        ///  
        /// For a given extent, returns the function mapping translator.
        ///  
        /// Association set or entity set for which to retrieve a translator
        /// Function translator or null if none exists for this extent
        internal FunctionMappingTranslator GetFunctionMappingTranslator(EntitySetBase extent)
        { 
            return SyncGetValue(m_functionMappingTranslators, extent);
        } 
 
        /// 
        /// Returns store tables affected by modifications to a particular C-layer extent. Although this 
        /// information can be inferred from the update view, we want to avoid compiling or loading
        /// views when not required. This information can be directly determined from mapping metadata.
        /// 
        /// C-layer extent. 
        /// Affected store tables.
        internal Set GetAffectedTables(EntitySetBase extent) 
        { 
            return SyncGetValue(m_affectedTables, extent);
        } 

        /// 
        /// Gets information relevant to the processing of an AssociationSet in the update pipeline.
        /// Caches information on first retrieval. 
        /// 
        internal AssociationSetMetadata GetAssociationSetMetadata(AssociationSet associationSet) 
        { 
            return SyncGetValue(m_associationSetMetadata, associationSet);
        } 

        /// 
        /// Determines whether the given member maps to a server-generated column in the store.
        /// Requires: InitializeExtentInformation has been called for the extent being persisted. 
        /// 
        /// Member to lookup 
        /// Whether the member is server generated in some context 
        internal bool IsServerGen(EdmMember member)
        { 
            return SyncContains(m_serverGenProperties, member);
        }

        ///  
        /// Determines whether the given member maps to a column participating in an isnull
        /// condition. Useful to determine if a nullability constraint violation is going to 
        /// cause roundtripping problems (e.g. if type is based on nullability of a 'non-nullable' 
        /// property of a derived entity type)
        ///  
        internal bool IsNullConditionMember(EdmMember member)
        {
            return SyncContains(m_isNullConditionProperties, member);
        } 

        ///  
        /// Utility method reading value from dictionary within read lock. 
        /// 
        private T_Value SyncGetValue(Dictionary dictionary, T_Key key) 
        {
            m_readerWriterLock.EnterReadLock();
            try
            { 
                return dictionary[key];
            } 
            finally 
            {
                m_readerWriterLock.ExitReadLock(); 
            }
        }

        ///  
        /// Utility method checking for membership of element in set within read lock.
        ///  
        private bool SyncContains(Set set, T_Element element) 
        {
            m_readerWriterLock.EnterReadLock(); 
            try
            {
                return set.Contains(element);
            } 
            finally
            { 
                m_readerWriterLock.ExitReadLock(); 
            }
        } 

        /// 
        /// Initializes all information relevant to the entity set.
        ///  
        /// Association set or entity set to load.
        /// metadata workspace 
        internal void SyncInitializeEntitySet(EntitySetBase entitySetBase, MetadataWorkspace workspace) 
        {
            m_readerWriterLock.EnterReadLock(); 
            try
            {
                // check if we've already done the work for this entity set
                if (m_affectedTables.ContainsKey(entitySetBase)) 
                {
                    return; 
                } 
            }
            finally 
            {
                m_readerWriterLock.ExitReadLock();
            }
 
            // acquire a write lock
            m_readerWriterLock.EnterWriteLock(); 
            try 
            {
                // see if we've since done the work for this entity set 
                if (m_affectedTables.ContainsKey(entitySetBase))
                {
                    return;
                } 

                InitializeEntitySet(entitySetBase, workspace); 
            } 
            finally
            { 
                m_readerWriterLock.ExitWriteLock();
            }
        }
 
        private void InitializeEntitySet(EntitySetBase entitySetBase, MetadataWorkspace workspace)
        { 
            // make sure views have been generated for this sub-graph (trigger generation of the sub-graph 
            // by retrieving a view for one of its components; not actually using the view here)
            m_mappingItemCollection.GetGeneratedView(entitySetBase, workspace); 
            Set affectedTables = new Set();

            StorageEntityContainerMapping mapping = (StorageEntityContainerMapping)m_mappingItemCollection.GetMap(entitySetBase.EntityContainer);
 
            if (null != mapping)
            { 
                Set isNullConditionColumns = new Set(); 

                // find extent in the container mapping 
                StorageSetMapping setMapping;
                if (entitySetBase.BuiltInTypeKind == BuiltInTypeKind.EntitySet)
                {
                    setMapping = mapping.GetEntitySetMapping(entitySetBase.Name); 

                    // Check for members that have result bindings in a function mapping. If a 
                    // function returns the member values, it indicates they are server-generated 
                    m_serverGenProperties.Unite(GetMembersWithResultBinding((StorageEntitySetMapping)setMapping));
                } 
                else if (entitySetBase.BuiltInTypeKind == BuiltInTypeKind.AssociationSet)
                {
                    setMapping = mapping.GetRelationshipSetMapping(entitySetBase.Name);
                } 
                else
                { 
                    Debug.Fail("unexpected extent type " + entitySetBase.BuiltInTypeKind); 
                    throw EntityUtil.NotSupported();
                } 

                // gather interesting tables, columns and properties from mapping fragments
                foreach (StorageMappingFragment mappingFragment in GetMappingFragments(setMapping))
                { 
                    affectedTables.Add(mappingFragment.TableSet);
 
                    // get all property mappings to figure out if anything is server generated 
                    m_serverGenProperties.AddRange(FindServerGenMembers(mappingFragment));
 
                    // get all columns participating in is null conditions
                    isNullConditionColumns.AddRange(FindIsNullConditionColumns(mappingFragment));
                }
 
                if (0 < isNullConditionColumns.Count)
                { 
                    // gather is null condition properties based on is null condition columns 
                    foreach (StorageMappingFragment mappingFragment in GetMappingFragments(setMapping))
                    { 
                        m_isNullConditionProperties.AddRange(FindPropertiesMappedToColumns(isNullConditionColumns, mappingFragment));
                    }
                }
            } 

            m_affectedTables.Add(entitySetBase, affectedTables.MakeReadOnly()); 
 
            InitializeFunctionMappingTranslators(entitySetBase, mapping);
 
            // for association sets, initialize AssociationSetMetadata if no function has claimed ownership
            // of the association yet
            if (entitySetBase.BuiltInTypeKind == BuiltInTypeKind.AssociationSet)
            { 
                AssociationSet associationSet = (AssociationSet)entitySetBase;
                if (!m_associationSetMetadata.ContainsKey(associationSet)) 
                { 
                    m_associationSetMetadata.Add(associationSet, new AssociationSetMetadata(
                        m_affectedTables[associationSet], associationSet, workspace)); 
                }
            }
        }
 
        /// 
        /// Yields all members appearing in function mapping result bindings. 
        ///  
        /// Set mapping to examine
        /// All result bindings 
        private IEnumerable GetMembersWithResultBinding(StorageEntitySetMapping entitySetMapping)
        {
            foreach (StorageEntityTypeFunctionMapping typeFunctionMapping in entitySetMapping.FunctionMappings)
            { 
                // look at all result bindings for insert and update commands
                if (null != typeFunctionMapping.InsertFunctionMapping.ResultBindings) 
                { 
                    foreach (StorageFunctionResultBinding binding in typeFunctionMapping.InsertFunctionMapping.ResultBindings)
                    { 
                        yield return binding.Property;
                    }
                }
                if (null != typeFunctionMapping.UpdateFunctionMapping.ResultBindings) 
                {
                    foreach (StorageFunctionResultBinding binding in typeFunctionMapping.UpdateFunctionMapping.ResultBindings) 
                    { 
                        yield return binding.Property;
                    } 
                }
            }
        }
 
        // Loads and registers any function mapping translators for the given extent (and related container)
        private void InitializeFunctionMappingTranslators(EntitySetBase entitySetBase, StorageEntityContainerMapping mapping) 
        { 
            KeyToListMap requiredEnds = new KeyToListMap(
                EqualityComparer.Default); 

            // see if function mapping metadata needs to be processed
            if (!m_functionMappingTranslators.ContainsKey(entitySetBase))
            { 
                // load all function mapping data from the current entity container
                foreach (StorageEntitySetMapping entitySetMapping in mapping.EntitySetMaps) 
                { 
                    if (0 < entitySetMapping.FunctionMappings.Count)
                    { 
                        // register the function mapping
                        m_functionMappingTranslators.Add(entitySetMapping.Set, FunctionMappingTranslator.CreateEntitySetFunctionMappingTranslator(entitySetMapping));

                        // register "null" function translators for all implicitly mapped association sets 
                        foreach (AssociationSetEnd end in entitySetMapping.ImplicitlyMappedAssociationSetEnds)
                        { 
                            AssociationSet associationSet = end.ParentAssociationSet; 
                            if (!m_functionMappingTranslators.ContainsKey(associationSet))
                            { 
                                m_functionMappingTranslators.Add(associationSet, FunctionMappingTranslator.CreateAssociationSetFunctionMappingTranslator(null));
                            }

                            // Remember that the current entity set is required for all updates to the collocated 
                            // relationship set. This entity set's end is opposite the target end for the mapping.
                            AssociationSetEnd oppositeEnd = MetadataHelper.GetOppositeEnd(end); 
                            requiredEnds.Add(associationSet, oppositeEnd.CorrespondingAssociationEndMember); 
                        }
                    } 
                    else
                    {
                        // register null translator (so that we never attempt to process this extent again)
                        m_functionMappingTranslators.Add(entitySetMapping.Set, null); 
                    }
                } 
 
                foreach (StorageAssociationSetMapping associationSetMapping in mapping.RelationshipSetMaps)
                { 
                    if (null != associationSetMapping.FunctionMapping)
                    {
                        AssociationSet set = (AssociationSet)associationSetMapping.Set;
 
                        // use indexer rather than Add since the association set may already have an implicit function
                        // mapping -- this explicit function mapping takes precedence in such cases 
                        m_functionMappingTranslators.Add(set, 
                            FunctionMappingTranslator.CreateAssociationSetFunctionMappingTranslator(associationSetMapping));
 
                        // remember that we've seen a function mapping for this association set, which overrides
                        // any other behaviors for determining required/optional ends
                        requiredEnds.AddRange(set, Enumerable.Empty());
                    } 
                    else
                    { 
                        if (!m_functionMappingTranslators.ContainsKey(associationSetMapping.Set)) 
                        {
                            // register null translator (so that we never attempt to process this extent again) 
                            m_functionMappingTranslators.Add(associationSetMapping.Set, null);
                        }
                    }
                } 
            }
 
            // register association metadata for all association sets encountered 
            foreach (AssociationSet associationSet in requiredEnds.Keys)
            { 
                m_associationSetMetadata.Add(associationSet, new AssociationSetMetadata(
                    requiredEnds.EnumerateValues(associationSet)));
            }
        } 

        ///  
        /// Gets all model properties mapped to server generated columns. 
        /// 
        private static IEnumerable FindServerGenMembers(StorageMappingFragment mappingFragment) 
        {
            foreach (var scalarPropertyMapping in FlattenPropertyMappings(mappingFragment.AllProperties)
                .OfType())
            { 
                if (StoreGeneratedPattern.None != MetadataHelper.GetStoreGeneratedPattern(scalarPropertyMapping.ColumnProperty))
                { 
                    yield return scalarPropertyMapping.EdmProperty; 
                }
            } 
        }

        /// 
        /// Gets all store columns participating in is null conditions. 
        /// 
        private static IEnumerable FindIsNullConditionColumns(StorageMappingFragment mappingFragment) 
        { 
            foreach (var conditionPropertyMapping in FlattenPropertyMappings(mappingFragment.AllProperties)
                .OfType()) 
            {
                if (conditionPropertyMapping.ColumnProperty != null &&
                    conditionPropertyMapping.IsNull.HasValue)
                { 
                    yield return conditionPropertyMapping.ColumnProperty;
                } 
            } 
        }
 
        /// 
        /// Gets all model properties mapped to given columns.
        /// 
        private static IEnumerable FindPropertiesMappedToColumns(Set columns, StorageMappingFragment mappingFragment) 
        {
            foreach (var scalarPropertyMapping in FlattenPropertyMappings(mappingFragment.AllProperties) 
                .OfType()) 
            {
                if (columns.Contains(scalarPropertyMapping.ColumnProperty)) 
                {
                    yield return scalarPropertyMapping.EdmProperty;
                }
            } 
        }
 
        ///  
        /// Enumerates all mapping fragments in given set mapping.
        ///  
        private static IEnumerable GetMappingFragments(StorageSetMapping setMapping)
        {
            // get all type mappings for the extent
            foreach (StorageTypeMapping typeMapping in setMapping.TypeMappings) 
            {
                // get all table mapping fragments for the type 
                foreach (StorageMappingFragment mappingFragment in typeMapping.MappingFragments) 
                {
                    yield return mappingFragment; 
                }
            }
        }
 
        /// 
        /// Returns all bottom-level mappings (e.g. conditions and scalar property mappings but not complex property mappings 
        /// whose components are returned) 
        /// 
        private static IEnumerable FlattenPropertyMappings(System.Collections.ObjectModel.ReadOnlyCollection propertyMappings) 
        {
            foreach (StoragePropertyMapping propertyMapping in propertyMappings)
            {
                StorageComplexPropertyMapping complexPropertyMapping = propertyMapping as StorageComplexPropertyMapping; 
                if (null != complexPropertyMapping)
                { 
                    foreach (StorageComplexTypeMapping complexTypeMapping in complexPropertyMapping.TypeMappings) 
                    {
                        // recursively call self with nested type 
                        foreach (StoragePropertyMapping nestedPropertyMapping in FlattenPropertyMappings(complexTypeMapping.AllProperties))
                        {
                            yield return nestedPropertyMapping;
                        } 
                    }
                } 
                else 
                {
                    yield return propertyMapping; 
                }
            }
        }
        #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