ExtractorMetadata.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Map / Update / Internal / ExtractorMetadata.cs / 2 / ExtractorMetadata.cs

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

using System.Data.Metadata.Edm; 
using System.Collections;
using System.Collections.Generic;
using System.Data.Common.Utils;
using System.Data.Objects; 
using System.Diagnostics;
using System.Data.Common; 
using System.Linq; 
using System.Data.Entity;
namespace System.Data.Mapping.Update.Internal 
{
    /// 
    /// Encapsulates metadata information relevant to update for records extracted from
    /// the entity state manager, such as concurrency flags and key information. 
    /// 
    internal class ExtractorMetadata 
    { 
        internal ExtractorMetadata(StructuralType type, UpdateTranslator translator)
        { 
            m_type = EntityUtil.CheckArgumentNull(type, "type");
            m_translator = EntityUtil.CheckArgumentNull(translator, "translator");

            Set keyMembers; 

            switch (type.BuiltInTypeKind) 
            { 
                case BuiltInTypeKind.RowType:
                    // for row types (which are actually association end key records in disguise), all members 
                    // are keys
                    keyMembers = new Set(type.Members).MakeReadOnly();
                    break;
                case BuiltInTypeKind.EntityType: 
                    keyMembers = new Set(((EntityType)type).KeyMembers).MakeReadOnly();
                    break; 
                default: 
                    keyMembers = Set.Empty;
                    break; 
            }

            m_memberMap = new Dictionary();
            IBaseList members = TypeHelpers.GetAllStructuralMembers(type); 
            // for each member, cache expensive to compute metadata information
            for (int ordinal = 0; ordinal < members.Count; ordinal++) 
            { 
                EdmMember member = members[ordinal];
                // figure out flags for this member 
                PropagatorFlags flags = PropagatorFlags.NoFlags;

                if (keyMembers.Contains(member))
                { 
                    flags |= PropagatorFlags.Key;
                } 
 
                if (MetadataHelper.GetConcurrencyMode(member) == ConcurrencyMode.Fixed)
                { 
                    flags |= PropagatorFlags.ConcurrencyValue;
                }

                // figure out whether this member is mapped to any server generated 
                // columns in the store
                bool isServerGenerated = m_translator.ViewLoader.IsServerGen(member); 
 
                // figure out whether member nullability is used as a condition in mapping
                bool isNullConditionMember = m_translator.ViewLoader.IsNullConditionMember(member); 

                // add information about this member
                m_memberMap.Add(member.Name, new MemberInformation(ordinal, flags, member, isServerGenerated, isNullConditionMember));
            } 
        }
 
        private readonly Dictionary m_memberMap; 
        private readonly StructuralType m_type;
        private readonly UpdateTranslator m_translator; 

        /// 
        /// Given a state entry, returns a bit array indicating which members
        /// have been modified by ordinal. 
        /// Requires: state entry matches the type metadata described by this instance.
        ///  
        ///  
        /// state manager entry for which to identify modified properties
        /// Modified properties bit array. If null is returned, this indicates all properties 
        /// are modified.
        internal BitArray GetModifiedPropertiesBitArray(IEnumerable modifiedProperties, IEntityStateEntry stateEntry)
        {
            int memberCount = TypeHelpers.GetAllStructuralMembers(m_type).Count; 

            if (null == modifiedProperties) 
            { 
                // all properties are modified when the state entry is not being modified (it's being inserted
                // or deleted) or the modified list is null 
                return null;
            }

            BitArray result = new BitArray(memberCount, false); 

            foreach (string modifiedProperty in modifiedProperties) 
            { 
                MemberInformation memberInformation;
                if (!m_memberMap.TryGetValue(modifiedProperty, out memberInformation)) 
                {
                    throw EntityUtil.Update(System.Data.Entity.Strings.Update_MissingModifiedProperty(modifiedProperty, m_type.Name), null, stateEntry);
                }
                result[memberInformation.Ordinal] = true; 
            }
 
            return result; 
        }
 
        /// 
        /// Requires: record must have correct type for this metadata instance.
        /// Populates a new  object representing a member of a record matching the
        /// type of this extractor. Given a record and a member, this method wraps the value of the member 
        /// in a PropagatorResult. This operation can be performed efficiently by this class, which knows
        /// important stuff about the type being extracted. 
        ///  
        /// state manager entry containing value (used for error reporting)
        /// Record containing value (used to find the actual value) 
        /// Entity key for the state entry. Must be set for entity records.
        /// Member for which to retrieve a value.
        /// Bit array indicating which members of the type are
        /// modified (must be ordinally aligned with the type). Null indicates all members are modified. 
        /// Propagator result describing this member value.
        internal PropagatorResult RetrieveMember(IEntityStateEntry stateEntry, IExtendedDataRecord record, 
            EntityKey key, EdmMember member, BitArray modifiedProperties) 
        {
            MemberInformation memberInformation = m_memberMap[member.Name]; 

            // get identifier value
            Int64 identifier;
            if (memberInformation.IsKeyMember) 
            {
                // retrieve identifier for this key member 
                Debug.Assert(null != (object)key, "entities must have keys, and only entity members are marked IsKeyMember by " + 
                    "the metadata wrapper");
                IList keyMembers = ((EntitySet)stateEntry.EntitySet).ElementType.KeyMembers; 
                int keyOrdinal = keyMembers.IndexOf(member);
                identifier = m_translator.KeyManager.GetKeyIdentifierForMemberOffset(key, keyOrdinal, keyMembers.Count);
            }
            else 
            {
                identifier = PropagatorResult.NullIdentifier; 
            } 

            // determine if the member is modified 
            bool isModified = null == modifiedProperties || // null indicates all properties are modified
                modifiedProperties[memberInformation.Ordinal];

            // determine member value 
            int recordOrdinal = record.GetOrdinal(member.Name);
            if (memberInformation.CheckIsNotNull && record.IsDBNull(recordOrdinal)) 
            { 
                throw EntityUtil.Update(Strings.Update_NullValue(member.Name), null, stateEntry);
            } 
            object value = record.GetValue(recordOrdinal);

            // determine what kind of member this is
 
            // entityKey (association end)
            EntityKey entityKey = value as EntityKey; 
            if (null != (object)entityKey) 
            {
                return CreateEntityKeyResult(stateEntry, entityKey); 
            }

            // record (nested complex type)
            IExtendedDataRecord nestedRecord = value as IExtendedDataRecord; 
            if (null != nestedRecord)
            { 
                // for structural types, we track whether the entire complex type value is modified or not 
                IEnumerable nestedModifiedPropertyNames = isModified ?
                    null : // indicates all properties are modified 
                    Enumerable.Empty(); // indicates no properties are modified
                UpdateTranslator translator = m_translator;

                return ExtractResultFromRecord(stateEntry, isModified, nestedRecord, nestedModifiedPropertyNames, translator); 
            }
 
            // simple value (column/property value) 
            return CreateSimpleResult(stateEntry, record, memberInformation, identifier, isModified, recordOrdinal, value);
        } 

        // Note that this is called only for association ends. Entities have key values inline.
        private PropagatorResult CreateEntityKeyResult(IEntityStateEntry stateEntry, EntityKey entityKey)
        { 
            // get metadata for key
            EntityType entityType = entityKey.GetEntitySet(m_translator.MetadataWorkspace).ElementType; 
            RowType keyRowType = entityType.GetKeyRowType(m_translator.MetadataWorkspace); 

            ExtractorMetadata keyMetadata = m_translator.GetExtractorMetadata(keyRowType); 
            int keyMemberCount = keyRowType.Members.Count;
            PropagatorResult[] keyValues = new PropagatorResult[keyMemberCount];

            for (int ordinal = 0; ordinal < keyRowType.Members.Count; ordinal++) 
            {
                EdmMember keyMember = keyRowType.Members[ordinal]; 
                // retrieve information about this key value 
                MemberInformation keyMemberInformation = keyMetadata.m_memberMap[keyMember.Name];
 
                long keyIdentifier = m_translator.KeyManager.GetKeyIdentifierForMemberOffset(entityKey, ordinal, keyRowType.Members.Count);

                object keyValue = null;
                if (entityKey.IsTemporary) 
                {
                    // If the EntityKey is temporary, we need to retrieve the appropriate 
                    // key value from the entity itself (or in this case, the IEntityStateEntry). 
                    IEntityStateEntry entityEntry = stateEntry.StateManager.GetEntityStateEntry(entityKey);
                    Debug.Assert(entityEntry.State == EntityState.Added, 
                        "The corresponding entry for a temp EntityKey should be in the Added State.");
                    keyValue = entityEntry.CurrentValues[keyMember.Name];
                }
                else 
                {
                    // Otherwise, we extract the value from within the EntityKey. 
                    keyValue = entityKey.FindValueByName(keyMember.Name); 
                }
                Debug.Assert(keyValue != null, "keyValue should've been retrieved."); 

                // construct propagator result
                keyValues[ordinal] = PropagatorResult.CreateKeyValue(
                    keyMemberInformation.Flags, 
                    keyValue,
                    stateEntry, 
                    keyIdentifier); 

                // see UpdateTranslator.Identifiers for information on key identifiers and ordinals 
            }

            return PropagatorResult.CreateStructuralValue(keyValues, keyMetadata.m_type, false);
        } 

        private PropagatorResult CreateSimpleResult(IEntityStateEntry stateEntry, IExtendedDataRecord record, MemberInformation memberInformation, 
            Int64 identifier, bool isModified, int recordOrdinal, object value) 
        {
            CurrentValueRecord updatableRecord = record as CurrentValueRecord; 

            // construct flags for the value, which is needed for complex type and simple members
            PropagatorFlags flags = memberInformation.Flags;
            if (!isModified) { flags |= PropagatorFlags.Preserve; } 
            if (PropagatorResult.NullIdentifier != identifier)
            { 
                // construct a key member 
                PropagatorResult result;
                if (memberInformation.IsServerGenerated && null != updatableRecord) 
                {
                    result = PropagatorResult.CreateServerGenKeyValue(flags, value, stateEntry, identifier, recordOrdinal);
                }
                else 
                {
                    result = PropagatorResult.CreateKeyValue(flags, value, stateEntry, identifier); 
                } 

                // we register the entity as the "owner" of an identity so that back-propagation can succeed 
                // (keys can only be back-propagated to entities, not association ends). It also allows us
                // to walk to the entity state entry in case of exceptions, since the state entry propagated
                // through the stack may be eliminated in a project above a join.
                m_translator.KeyManager.RegisterIdentifierOwner(result); 

                return result; 
            } 
            else
            { 
                if (memberInformation.IsServerGenerated && null != updatableRecord)
                {
                    // note: we only produce a server gen result when
                    return PropagatorResult.CreateServerGenSimpleValue(flags, value, updatableRecord, recordOrdinal); 
                }
                else 
                { 
                    return PropagatorResult.CreateSimpleValue(flags, value);
                } 
            }
        }

        ///  
        /// Converts a record to a propagator result
        ///  
        /// state manager entry containing the record 
        /// Indicates whether the root element is modified (i.e., whether the type has changed)
        /// Record to convert 
        /// Names of modified properties
        /// Translator for session context; registers new metadata for the record type if none
        /// exists
        /// Result corresponding to the given record 
        internal static PropagatorResult ExtractResultFromRecord(IEntityStateEntry stateEntry, bool isModified, IExtendedDataRecord record,
            IEnumerable modifiedPropertyNames, UpdateTranslator translator) 
        { 
            StructuralType structuralType = (StructuralType)record.DataRecordInfo.RecordType.EdmType;
            ExtractorMetadata metadata = translator.GetExtractorMetadata(structuralType); 
            EntityKey key = stateEntry.EntityKey;

            // get bit array describing modified properties
            BitArray modifiedProperties = metadata.GetModifiedPropertiesBitArray(modifiedPropertyNames, 
                stateEntry);
 
            // construct values for members of complex type 
            IBaseList members = TypeHelpers.GetAllStructuralMembers(structuralType);
 
            PropagatorResult[] nestedValues = new PropagatorResult[members.Count];
            for (int ordinal = 0; ordinal < nestedValues.Length; ordinal++)
            {
                EdmMember nestedMember = members[ordinal]; 
                nestedValues[ordinal] = metadata.RetrieveMember(stateEntry, record, key,
                    nestedMember, modifiedProperties); 
            } 

            return PropagatorResult.CreateStructuralValue(nestedValues, structuralType, isModified); 
        }

        private class MemberInformation
        { 
            /// 
            /// Gets ordinal of the member. 
            ///  
            internal readonly int Ordinal;
 
            /// 
            /// Gets propagator flags for the member, excluding the 'Preserve' flag
            /// which can only be set in context.
            ///  
            internal readonly PropagatorFlags Flags;
 
            ///  
            /// Indicates whether this is a key member.
            ///  
            internal bool IsKeyMember
            {
                get
                { 
                    return PropagatorFlags.Key == (Flags & PropagatorFlags.Key);
                } 
            } 

            ///  
            /// Indicates whether this value is server generated.
            /// 
            internal readonly bool IsServerGenerated;
 
            /// 
            /// Indicates whether non-null values are supported for this member. 
            ///  
            internal readonly bool CheckIsNotNull;
 
            /// 
            /// Gets the member described by this wrapper.
            /// 
            internal readonly EdmMember Member; 

            internal MemberInformation(int ordinal, PropagatorFlags flags, EdmMember member, bool isServerGenerated, bool isNullConditionMember) 
            { 
                this.Ordinal = ordinal;
                this.Flags = flags; 
                this.Member = member;
                this.IsServerGenerated = isServerGenerated;
                // in two cases, we must check that a member value is not null:
                // - where the type participates in an isnull condition, nullability constraints must be honored 
                // - for complex types, mapping relies on nullability constraint
                // - in other cases, nullability does not impact round trippability so we don't check 
                this.CheckIsNotNull = !TypeSemantics.IsNullable(member) && 
                    (isNullConditionMember || member.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType);
            } 
        }
    }
}

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

using System.Data.Metadata.Edm; 
using System.Collections;
using System.Collections.Generic;
using System.Data.Common.Utils;
using System.Data.Objects; 
using System.Diagnostics;
using System.Data.Common; 
using System.Linq; 
using System.Data.Entity;
namespace System.Data.Mapping.Update.Internal 
{
    /// 
    /// Encapsulates metadata information relevant to update for records extracted from
    /// the entity state manager, such as concurrency flags and key information. 
    /// 
    internal class ExtractorMetadata 
    { 
        internal ExtractorMetadata(StructuralType type, UpdateTranslator translator)
        { 
            m_type = EntityUtil.CheckArgumentNull(type, "type");
            m_translator = EntityUtil.CheckArgumentNull(translator, "translator");

            Set keyMembers; 

            switch (type.BuiltInTypeKind) 
            { 
                case BuiltInTypeKind.RowType:
                    // for row types (which are actually association end key records in disguise), all members 
                    // are keys
                    keyMembers = new Set(type.Members).MakeReadOnly();
                    break;
                case BuiltInTypeKind.EntityType: 
                    keyMembers = new Set(((EntityType)type).KeyMembers).MakeReadOnly();
                    break; 
                default: 
                    keyMembers = Set.Empty;
                    break; 
            }

            m_memberMap = new Dictionary();
            IBaseList members = TypeHelpers.GetAllStructuralMembers(type); 
            // for each member, cache expensive to compute metadata information
            for (int ordinal = 0; ordinal < members.Count; ordinal++) 
            { 
                EdmMember member = members[ordinal];
                // figure out flags for this member 
                PropagatorFlags flags = PropagatorFlags.NoFlags;

                if (keyMembers.Contains(member))
                { 
                    flags |= PropagatorFlags.Key;
                } 
 
                if (MetadataHelper.GetConcurrencyMode(member) == ConcurrencyMode.Fixed)
                { 
                    flags |= PropagatorFlags.ConcurrencyValue;
                }

                // figure out whether this member is mapped to any server generated 
                // columns in the store
                bool isServerGenerated = m_translator.ViewLoader.IsServerGen(member); 
 
                // figure out whether member nullability is used as a condition in mapping
                bool isNullConditionMember = m_translator.ViewLoader.IsNullConditionMember(member); 

                // add information about this member
                m_memberMap.Add(member.Name, new MemberInformation(ordinal, flags, member, isServerGenerated, isNullConditionMember));
            } 
        }
 
        private readonly Dictionary m_memberMap; 
        private readonly StructuralType m_type;
        private readonly UpdateTranslator m_translator; 

        /// 
        /// Given a state entry, returns a bit array indicating which members
        /// have been modified by ordinal. 
        /// Requires: state entry matches the type metadata described by this instance.
        ///  
        ///  
        /// state manager entry for which to identify modified properties
        /// Modified properties bit array. If null is returned, this indicates all properties 
        /// are modified.
        internal BitArray GetModifiedPropertiesBitArray(IEnumerable modifiedProperties, IEntityStateEntry stateEntry)
        {
            int memberCount = TypeHelpers.GetAllStructuralMembers(m_type).Count; 

            if (null == modifiedProperties) 
            { 
                // all properties are modified when the state entry is not being modified (it's being inserted
                // or deleted) or the modified list is null 
                return null;
            }

            BitArray result = new BitArray(memberCount, false); 

            foreach (string modifiedProperty in modifiedProperties) 
            { 
                MemberInformation memberInformation;
                if (!m_memberMap.TryGetValue(modifiedProperty, out memberInformation)) 
                {
                    throw EntityUtil.Update(System.Data.Entity.Strings.Update_MissingModifiedProperty(modifiedProperty, m_type.Name), null, stateEntry);
                }
                result[memberInformation.Ordinal] = true; 
            }
 
            return result; 
        }
 
        /// 
        /// Requires: record must have correct type for this metadata instance.
        /// Populates a new  object representing a member of a record matching the
        /// type of this extractor. Given a record and a member, this method wraps the value of the member 
        /// in a PropagatorResult. This operation can be performed efficiently by this class, which knows
        /// important stuff about the type being extracted. 
        ///  
        /// state manager entry containing value (used for error reporting)
        /// Record containing value (used to find the actual value) 
        /// Entity key for the state entry. Must be set for entity records.
        /// Member for which to retrieve a value.
        /// Bit array indicating which members of the type are
        /// modified (must be ordinally aligned with the type). Null indicates all members are modified. 
        /// Propagator result describing this member value.
        internal PropagatorResult RetrieveMember(IEntityStateEntry stateEntry, IExtendedDataRecord record, 
            EntityKey key, EdmMember member, BitArray modifiedProperties) 
        {
            MemberInformation memberInformation = m_memberMap[member.Name]; 

            // get identifier value
            Int64 identifier;
            if (memberInformation.IsKeyMember) 
            {
                // retrieve identifier for this key member 
                Debug.Assert(null != (object)key, "entities must have keys, and only entity members are marked IsKeyMember by " + 
                    "the metadata wrapper");
                IList keyMembers = ((EntitySet)stateEntry.EntitySet).ElementType.KeyMembers; 
                int keyOrdinal = keyMembers.IndexOf(member);
                identifier = m_translator.KeyManager.GetKeyIdentifierForMemberOffset(key, keyOrdinal, keyMembers.Count);
            }
            else 
            {
                identifier = PropagatorResult.NullIdentifier; 
            } 

            // determine if the member is modified 
            bool isModified = null == modifiedProperties || // null indicates all properties are modified
                modifiedProperties[memberInformation.Ordinal];

            // determine member value 
            int recordOrdinal = record.GetOrdinal(member.Name);
            if (memberInformation.CheckIsNotNull && record.IsDBNull(recordOrdinal)) 
            { 
                throw EntityUtil.Update(Strings.Update_NullValue(member.Name), null, stateEntry);
            } 
            object value = record.GetValue(recordOrdinal);

            // determine what kind of member this is
 
            // entityKey (association end)
            EntityKey entityKey = value as EntityKey; 
            if (null != (object)entityKey) 
            {
                return CreateEntityKeyResult(stateEntry, entityKey); 
            }

            // record (nested complex type)
            IExtendedDataRecord nestedRecord = value as IExtendedDataRecord; 
            if (null != nestedRecord)
            { 
                // for structural types, we track whether the entire complex type value is modified or not 
                IEnumerable nestedModifiedPropertyNames = isModified ?
                    null : // indicates all properties are modified 
                    Enumerable.Empty(); // indicates no properties are modified
                UpdateTranslator translator = m_translator;

                return ExtractResultFromRecord(stateEntry, isModified, nestedRecord, nestedModifiedPropertyNames, translator); 
            }
 
            // simple value (column/property value) 
            return CreateSimpleResult(stateEntry, record, memberInformation, identifier, isModified, recordOrdinal, value);
        } 

        // Note that this is called only for association ends. Entities have key values inline.
        private PropagatorResult CreateEntityKeyResult(IEntityStateEntry stateEntry, EntityKey entityKey)
        { 
            // get metadata for key
            EntityType entityType = entityKey.GetEntitySet(m_translator.MetadataWorkspace).ElementType; 
            RowType keyRowType = entityType.GetKeyRowType(m_translator.MetadataWorkspace); 

            ExtractorMetadata keyMetadata = m_translator.GetExtractorMetadata(keyRowType); 
            int keyMemberCount = keyRowType.Members.Count;
            PropagatorResult[] keyValues = new PropagatorResult[keyMemberCount];

            for (int ordinal = 0; ordinal < keyRowType.Members.Count; ordinal++) 
            {
                EdmMember keyMember = keyRowType.Members[ordinal]; 
                // retrieve information about this key value 
                MemberInformation keyMemberInformation = keyMetadata.m_memberMap[keyMember.Name];
 
                long keyIdentifier = m_translator.KeyManager.GetKeyIdentifierForMemberOffset(entityKey, ordinal, keyRowType.Members.Count);

                object keyValue = null;
                if (entityKey.IsTemporary) 
                {
                    // If the EntityKey is temporary, we need to retrieve the appropriate 
                    // key value from the entity itself (or in this case, the IEntityStateEntry). 
                    IEntityStateEntry entityEntry = stateEntry.StateManager.GetEntityStateEntry(entityKey);
                    Debug.Assert(entityEntry.State == EntityState.Added, 
                        "The corresponding entry for a temp EntityKey should be in the Added State.");
                    keyValue = entityEntry.CurrentValues[keyMember.Name];
                }
                else 
                {
                    // Otherwise, we extract the value from within the EntityKey. 
                    keyValue = entityKey.FindValueByName(keyMember.Name); 
                }
                Debug.Assert(keyValue != null, "keyValue should've been retrieved."); 

                // construct propagator result
                keyValues[ordinal] = PropagatorResult.CreateKeyValue(
                    keyMemberInformation.Flags, 
                    keyValue,
                    stateEntry, 
                    keyIdentifier); 

                // see UpdateTranslator.Identifiers for information on key identifiers and ordinals 
            }

            return PropagatorResult.CreateStructuralValue(keyValues, keyMetadata.m_type, false);
        } 

        private PropagatorResult CreateSimpleResult(IEntityStateEntry stateEntry, IExtendedDataRecord record, MemberInformation memberInformation, 
            Int64 identifier, bool isModified, int recordOrdinal, object value) 
        {
            CurrentValueRecord updatableRecord = record as CurrentValueRecord; 

            // construct flags for the value, which is needed for complex type and simple members
            PropagatorFlags flags = memberInformation.Flags;
            if (!isModified) { flags |= PropagatorFlags.Preserve; } 
            if (PropagatorResult.NullIdentifier != identifier)
            { 
                // construct a key member 
                PropagatorResult result;
                if (memberInformation.IsServerGenerated && null != updatableRecord) 
                {
                    result = PropagatorResult.CreateServerGenKeyValue(flags, value, stateEntry, identifier, recordOrdinal);
                }
                else 
                {
                    result = PropagatorResult.CreateKeyValue(flags, value, stateEntry, identifier); 
                } 

                // we register the entity as the "owner" of an identity so that back-propagation can succeed 
                // (keys can only be back-propagated to entities, not association ends). It also allows us
                // to walk to the entity state entry in case of exceptions, since the state entry propagated
                // through the stack may be eliminated in a project above a join.
                m_translator.KeyManager.RegisterIdentifierOwner(result); 

                return result; 
            } 
            else
            { 
                if (memberInformation.IsServerGenerated && null != updatableRecord)
                {
                    // note: we only produce a server gen result when
                    return PropagatorResult.CreateServerGenSimpleValue(flags, value, updatableRecord, recordOrdinal); 
                }
                else 
                { 
                    return PropagatorResult.CreateSimpleValue(flags, value);
                } 
            }
        }

        ///  
        /// Converts a record to a propagator result
        ///  
        /// state manager entry containing the record 
        /// Indicates whether the root element is modified (i.e., whether the type has changed)
        /// Record to convert 
        /// Names of modified properties
        /// Translator for session context; registers new metadata for the record type if none
        /// exists
        /// Result corresponding to the given record 
        internal static PropagatorResult ExtractResultFromRecord(IEntityStateEntry stateEntry, bool isModified, IExtendedDataRecord record,
            IEnumerable modifiedPropertyNames, UpdateTranslator translator) 
        { 
            StructuralType structuralType = (StructuralType)record.DataRecordInfo.RecordType.EdmType;
            ExtractorMetadata metadata = translator.GetExtractorMetadata(structuralType); 
            EntityKey key = stateEntry.EntityKey;

            // get bit array describing modified properties
            BitArray modifiedProperties = metadata.GetModifiedPropertiesBitArray(modifiedPropertyNames, 
                stateEntry);
 
            // construct values for members of complex type 
            IBaseList members = TypeHelpers.GetAllStructuralMembers(structuralType);
 
            PropagatorResult[] nestedValues = new PropagatorResult[members.Count];
            for (int ordinal = 0; ordinal < nestedValues.Length; ordinal++)
            {
                EdmMember nestedMember = members[ordinal]; 
                nestedValues[ordinal] = metadata.RetrieveMember(stateEntry, record, key,
                    nestedMember, modifiedProperties); 
            } 

            return PropagatorResult.CreateStructuralValue(nestedValues, structuralType, isModified); 
        }

        private class MemberInformation
        { 
            /// 
            /// Gets ordinal of the member. 
            ///  
            internal readonly int Ordinal;
 
            /// 
            /// Gets propagator flags for the member, excluding the 'Preserve' flag
            /// which can only be set in context.
            ///  
            internal readonly PropagatorFlags Flags;
 
            ///  
            /// Indicates whether this is a key member.
            ///  
            internal bool IsKeyMember
            {
                get
                { 
                    return PropagatorFlags.Key == (Flags & PropagatorFlags.Key);
                } 
            } 

            ///  
            /// Indicates whether this value is server generated.
            /// 
            internal readonly bool IsServerGenerated;
 
            /// 
            /// Indicates whether non-null values are supported for this member. 
            ///  
            internal readonly bool CheckIsNotNull;
 
            /// 
            /// Gets the member described by this wrapper.
            /// 
            internal readonly EdmMember Member; 

            internal MemberInformation(int ordinal, PropagatorFlags flags, EdmMember member, bool isServerGenerated, bool isNullConditionMember) 
            { 
                this.Ordinal = ordinal;
                this.Flags = flags; 
                this.Member = member;
                this.IsServerGenerated = isServerGenerated;
                // in two cases, we must check that a member value is not null:
                // - where the type participates in an isnull condition, nullability constraints must be honored 
                // - for complex types, mapping relies on nullability constraint
                // - in other cases, nullability does not impact round trippability so we don't check 
                this.CheckIsNotNull = !TypeSemantics.IsNullable(member) && 
                    (isNullConditionMember || member.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType);
            } 
        }
    }
}

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