PropagatorResult.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Map / Update / Internal / PropagatorResult.cs / 1305376 / PropagatorResult.cs

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

using System.Data.Metadata.Edm; 
using System.Collections.Generic;
using System.Globalization;
using System.Diagnostics;
using System.Data.Common.Utils; 
using System.Data.Objects;
using System.Collections; 
using System.Data.Common; 
using System.Text;
using System.Linq; 
namespace System.Data.Mapping.Update.Internal
{
    /// 
    /// requires: for structural types, member values are ordinally aligned with the members of the 
    /// structural type.
    /// 
    /// Stores a 'row' (or element within a row) being propagated through the update pipeline, including 
    /// markup information and metadata. Internally, we maintain several different classes so that we only
    /// store the necessary state. 
    ///
    /// - StructuralValue (complex types, entities, and association end keys): type and member values,
    ///   one version for modified structural values and one version for unmodified structural values
    ///   (a structural type is modified if its _type_ is changed, not its values 
    /// - SimpleValue (scalar value): flags to describe the state of the value (is it a concurrency value,
    ///   is it modified) and the value itself 
    /// - ServerGenSimpleValue: adds back-prop information to the above (record and position in record 
    ///   so that we can set the value on back-prop)
    /// - KeyValue: the originating IEntityStateEntry also travels with keys. These entries are used purely for 
    ///   error reporting. We send them with keys so that every row containing an entity (which must also
    ///   contain the key) has enough context to recover the state entry.
    /// 
    ///  
    /// Not all memebers of a PropagatorResult are available for all specializations. For instance, GetSimpleValue
    /// is available only on simple types 
    ///  
    internal abstract class PropagatorResult
    { 
        #region Constructors
        // private constructor: only nested classes may derive from propagator result
        private PropagatorResult()
        { 
        }
        #endregion 
 
        #region Fields
        internal const int NullIdentifier = -1; 
        internal const int NullOrdinal = -1;
        #endregion

        #region Properties 
        /// 
        /// Gets a value indicating whether this result is null. 
        ///  
        internal abstract bool IsNull { get; }
 
        /// 
        /// Gets a value indicating whether this is a simple (scalar) or complex
        /// structural) result.
        ///  
        internal abstract bool IsSimple { get; }
 
        ///  
        /// Gets flags describing the behaviors for this element.
        ///  
        internal virtual PropagatorFlags PropagatorFlags
        {
            get { return PropagatorFlags.NoFlags; }
        } 

        ///  
        /// Gets all state entries from which this result originated. Only set for key 
        /// values (to ensure every row knows all of its source entries)
        ///  
        internal virtual IEntityStateEntry StateEntry
        {
            get { return null; }
        } 

        ///  
        /// Gets record from which this result originated. Only set for server generated 
        /// results (where the record needs to be synchronized).
        ///  
        internal virtual CurrentValueRecord Record
        {
            get { return null; }
        } 

        ///  
        /// Gets structural type for non simple results. Only available for entity and complex type 
        /// results.
        ///  
        internal virtual StructuralType StructuralType
        {
            get { return null; }
        } 

        ///  
        /// Gets the ordinal within the originating record for this result. Only set 
        /// for server generated results (otherwise, returns -1)
        ///  
        internal virtual int RecordOrdinal
        {
            get { return NullOrdinal; }
        } 

        ///  
        /// Gets the identifier for this entry if it is a server-gen key value (otherwise 
        /// returns -1)
        ///  
        internal virtual int Identifier
        {
            get { return NullIdentifier; }
        } 

        ///  
        /// Where a single result corresponds to multiple key inputs, they are chained using this linked list. 
        /// By convention, the first entry in the chain is the 'dominant' entry (the principal key).
        ///  
        internal virtual PropagatorResult Next
        {
            get { return null; }
        } 
        #endregion
 
        #region Methods 
        /// 
        /// Returns simple value stored in this result. Only valid when  is 
        /// true.
        /// 
        ///
        /// Concrete value. 
        internal virtual object GetSimpleValue()
        { 
            throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.UpdatePipelineResultRequestInvalid, 0, "PropagatorResult.GetSimpleValue"); 
        }
 
        /// 
        /// Returns nested value. Only valid when  is false.
        /// 
        /// Ordinal of value to return (ordinal based on type definition) 
        /// Nested result.
        internal virtual PropagatorResult GetMemberValue(int ordinal) 
        { 
            throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.UpdatePipelineResultRequestInvalid, 0, "PropagatorResult.GetMemberValue");
        } 

        /// 
        /// Returns nested value. Only valid when  is false.
        ///  
        /// Member for which to return a value
        /// Nested result. 
        internal PropagatorResult GetMemberValue(EdmMember member) 
        {
            int ordinal = TypeHelpers.GetAllStructuralMembers(this.StructuralType).IndexOf(member); 
            return GetMemberValue(ordinal);
        }

        ///  
        /// Returns all structural values. Only valid when  is false.
        ///  
        /// Values of all structural members. 
        internal virtual PropagatorResult[] GetMemberValues()
        { 
            throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.UpdatePipelineResultRequestInvalid, 0, "PropagatorResult.GetMembersValues");
        }

        ///  
        /// Produces a replica of this propagator result with different flags.
        ///  
        /// New flags for the result. 
        /// This result with the given flags.
        internal abstract PropagatorResult ReplicateResultWithNewFlags(PropagatorFlags flags); 

        /// 
        /// Copies this result replacing its value. Used for cast. Requires a simple result.
        ///  
        /// New value for result
        /// Copy of this result with new value. 
        internal virtual PropagatorResult ReplicateResultWithNewValue(object value) 
        {
            throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.UpdatePipelineResultRequestInvalid, 0, "PropagatorResult.ReplicateResultWithNewValue"); 
        }

        /// 
        /// Replaces parts of the structured result. 
        /// 
        /// A replace-with map applied to simple (i.e. not structural) values. 
        /// Result with requested elements replaced. 
        internal abstract PropagatorResult Replace(Func map);
 
        /// 
        /// A result is merged with another when it is merged as part of an equi-join.
        /// 
        ///  
        /// In theory, this should only ever be called on two keys (since we only join on
        /// keys). We throw in the base implementation, and override in KeyResult. By convention 
        /// the principal key is always the first result in the chain (in case of an RIC). In 
        /// addition, entity entries always appear before relationship entries.
        ///  
        /// Result to merge with.
        /// Merged result.
        internal virtual PropagatorResult Merge(KeyManager keyManager, PropagatorResult other)
        { 
            throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.UpdatePipelineResultRequestInvalid, 0, "PropagatorResult.Merge");
        } 
 

#if DEBUG 
        public override string ToString()
        {
            StringBuilder builder = new StringBuilder();
            if (PropagatorFlags.NoFlags != PropagatorFlags) 
            {
                builder.Append(PropagatorFlags.ToString()).Append(":"); 
            } 
            if (NullIdentifier != Identifier)
            { 
                builder.Append("id").Append(Identifier.ToString(CultureInfo.InvariantCulture)).Append(":");
            }
            if (NullOrdinal != RecordOrdinal)
            { 
                builder.Append("ord").Append(RecordOrdinal.ToString(CultureInfo.InvariantCulture)).Append(":");
            } 
            if (IsSimple) 
            {
                builder.AppendFormat(CultureInfo.InvariantCulture, "{0}", GetSimpleValue()); 
            }
            else
            {
                if (!Helper.IsRowType(StructuralType)) 
                {
                    builder.Append(StructuralType.Name).Append(":"); 
                } 
                builder.Append("{");
                bool first = true; 
                foreach (KeyValuePair memberValue in Helper.PairEnumerations(
                    TypeHelpers.GetAllStructuralMembers(this.StructuralType), GetMemberValues()))
                {
                    if (first) { first = false; } 
                    else { builder.Append(", "); }
                    builder.Append(memberValue.Key.Name).Append("=").Append(memberValue.Value.ToString()); 
                } 
                builder.Append("}");
            } 
            return builder.ToString();
        }
#endif
        #endregion 

        #region Nested types and factory methods 
        internal static PropagatorResult CreateSimpleValue(PropagatorFlags flags, object value) 
        {
            return new SimpleValue(flags, value); 
        }

        private class SimpleValue : PropagatorResult
        { 
            internal SimpleValue(PropagatorFlags flags, object value)
            { 
                m_flags = flags; 
                m_value = value ?? DBNull.Value;
            } 

            private readonly PropagatorFlags m_flags;
            protected readonly object m_value;
 
            internal override PropagatorFlags PropagatorFlags
            { 
                get { return m_flags; } 
            }
 
            internal override bool IsSimple
            {
                get { return true; }
            } 

            internal override bool IsNull 
            { 
                get
                { 
                    // The result is null if it is not associated with an identifier and
                    // the value provided by the user is also null.
                    return NullIdentifier == this.Identifier && DBNull.Value == m_value;
                } 
            }
 
            internal override object GetSimpleValue() 
            {
                return m_value; 
            }

            internal override PropagatorResult ReplicateResultWithNewFlags(PropagatorFlags flags)
            { 
                return new SimpleValue(flags, m_value);
            } 
 
            internal override PropagatorResult ReplicateResultWithNewValue(object value)
            { 
                return new SimpleValue(PropagatorFlags, value);
            }

            internal override PropagatorResult Replace(Func map) 
            {
                return map(this); 
            } 
        }
 
        internal static PropagatorResult CreateServerGenSimpleValue(PropagatorFlags flags, object value, CurrentValueRecord record, int recordOrdinal)
        {
            return new ServerGenSimpleValue(flags, value, record, recordOrdinal);
        } 
        private class ServerGenSimpleValue : SimpleValue
        { 
            internal ServerGenSimpleValue(PropagatorFlags flags, object value, CurrentValueRecord record, int recordOrdinal) 
                : base(flags, value)
            { 
                Debug.Assert(null != record);

                m_record = record;
                m_recordOrdinal = recordOrdinal; 
            }
 
            private readonly CurrentValueRecord m_record; 
            private readonly int m_recordOrdinal;
 
            internal override CurrentValueRecord Record
            {
                get { return m_record; }
            } 

            internal override int RecordOrdinal 
            { 
                get { return m_recordOrdinal; }
            } 

            internal override PropagatorResult ReplicateResultWithNewFlags(PropagatorFlags flags)
            {
                return new ServerGenSimpleValue(flags, m_value, Record, RecordOrdinal); 
            }
 
            internal override PropagatorResult ReplicateResultWithNewValue(object value) 
            {
                return new ServerGenSimpleValue(PropagatorFlags, value, Record, RecordOrdinal); 
            }
        }

        internal static PropagatorResult CreateKeyValue(PropagatorFlags flags, object value, IEntityStateEntry stateEntry, int identifier) 
        {
            return new KeyValue(flags, value, stateEntry, identifier, null); 
        } 

        private class KeyValue : SimpleValue 
        {
            internal KeyValue(PropagatorFlags flags, object value, IEntityStateEntry stateEntry, int identifier, KeyValue next)
                : base(flags, value)
            { 
                Debug.Assert(null != stateEntry);
 
                m_stateEntry = stateEntry; 
                m_identifier = identifier;
                m_next = next; 
            }

            private readonly IEntityStateEntry m_stateEntry;
            private readonly int m_identifier; 
            protected readonly KeyValue m_next;
 
            internal override IEntityStateEntry StateEntry 
            {
                get { return m_stateEntry; } 
            }

            internal override int Identifier
            { 
                get { return m_identifier; }
            } 
 
            internal override CurrentValueRecord Record
            { 
                get
                {
                    // delegate to the state entry, which also has the record
                    return m_stateEntry.CurrentValues; 
                }
            } 
 
            internal override PropagatorResult Next
            { 
                get
                {
                    return m_next;
                } 
            }
 
            internal override PropagatorResult ReplicateResultWithNewFlags(PropagatorFlags flags) 
            {
                return new KeyValue(flags, m_value, StateEntry, Identifier, m_next); 
            }

            internal override PropagatorResult ReplicateResultWithNewValue(object value)
            { 
                return new KeyValue(PropagatorFlags, value, StateEntry, Identifier, m_next);
            } 
 
            internal virtual KeyValue ReplicateResultWithNewNext(KeyValue next)
            { 
                if (m_next != null)
                {
                    // push the next value to the end of the linked list
                    next = m_next.ReplicateResultWithNewNext(next); 
                }
                return new KeyValue(this.PropagatorFlags, m_value, m_stateEntry, m_identifier, next); 
            } 

            internal override PropagatorResult Merge(KeyManager keyManager, PropagatorResult other) 
            {
                KeyValue otherKey = other as KeyValue;
                if (null == otherKey)
                { 
                    EntityUtil.InternalError(EntityUtil.InternalErrorCode.UpdatePipelineResultRequestInvalid, 0, "KeyValue.Merge");
                } 
 
                // Determine which key (this or otherKey) is first in the chain. Principal keys take
                // precedence over dependent keys and entities take precedence over relationships. 
                if (this.Identifier != otherKey.Identifier)
                {
                    // Find principal (if any)
                    if (keyManager.GetPrincipals(otherKey.Identifier).Contains(this.Identifier)) 
                    {
                        return this.ReplicateResultWithNewNext(otherKey); 
                    } 
                    else
                    { 
                        return otherKey.ReplicateResultWithNewNext(this);
                    }
                }
                else 
                {
                    // Entity takes precedence of relationship 
                    if (null == m_stateEntry || m_stateEntry.IsRelationship) 
                    {
                        return otherKey.ReplicateResultWithNewNext(this); 
                    }
                    else
                    {
                        return this.ReplicateResultWithNewNext(otherKey); 
                    }
                } 
            } 
        }
 
        internal static PropagatorResult CreateServerGenKeyValue(PropagatorFlags flags, object value, IEntityStateEntry stateEntry, int identifier, int recordOrdinal)
        {
            return new ServerGenKeyValue(flags, value, stateEntry, identifier, recordOrdinal, null);
        } 

        private class ServerGenKeyValue : KeyValue 
        { 
            internal ServerGenKeyValue(PropagatorFlags flags, object value, IEntityStateEntry stateEntry, int identifier, int recordOrdinal, KeyValue next)
                : base(flags, value, stateEntry, identifier, next) 
            {
                m_recordOrdinal = recordOrdinal;
            }
 
            private readonly int m_recordOrdinal;
 
            internal override int RecordOrdinal 
            {
                get { return m_recordOrdinal; } 
            }

            internal override PropagatorResult ReplicateResultWithNewFlags(PropagatorFlags flags)
            { 
                return new ServerGenKeyValue(flags, m_value, this.StateEntry, this.Identifier, this.RecordOrdinal, m_next);
            } 
 
            internal override PropagatorResult ReplicateResultWithNewValue(object value)
            { 
                return new ServerGenKeyValue(this.PropagatorFlags, value, this.StateEntry, this.Identifier, this.RecordOrdinal, m_next);
            }

            internal override KeyValue ReplicateResultWithNewNext(KeyValue next) 
            {
                if (m_next != null) 
                { 
                    // push the next value to the end of the linked list
                    next = m_next.ReplicateResultWithNewNext(next); 
                }
                return new ServerGenKeyValue(PropagatorFlags, m_value, StateEntry, Identifier, RecordOrdinal, next);
            }
        } 

        internal static PropagatorResult CreateStructuralValue(PropagatorResult[] values, StructuralType structuralType, bool isModified) 
        { 
            if (isModified)
            { 
                return new StructuralValue(values, structuralType);
            }
            else
            { 
                return new UnmodifiedStructuralValue(values, structuralType);
            } 
        } 
        private class StructuralValue : PropagatorResult
        { 
            internal StructuralValue(PropagatorResult[] values, StructuralType structuralType)
            {
                Debug.Assert(null != structuralType);
                Debug.Assert(null != values); 
                Debug.Assert(values.Length == TypeHelpers.GetAllStructuralMembers(structuralType).Count);
 
                m_values = values; 
                m_structuralType = structuralType;
            } 

            private readonly PropagatorResult[] m_values;
            protected readonly StructuralType m_structuralType;
 
            internal override bool IsSimple
            { 
                get { return false; } 
            }
 
            internal override bool IsNull
            {
                get { return false; }
            } 

            internal override StructuralType StructuralType 
            { 
                get { return m_structuralType; }
            } 

            internal override PropagatorResult GetMemberValue(int ordinal)
            {
                return m_values[ordinal]; 
            }
 
            internal override PropagatorResult[] GetMemberValues() 
            {
                return m_values; 
            }

            internal override PropagatorResult ReplicateResultWithNewFlags(PropagatorFlags flags)
            { 
                throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.UpdatePipelineResultRequestInvalid, 0, "StructuralValue.ReplicateResultWithNewFlags");
            } 
 
            internal override PropagatorResult Replace(Func map)
            { 
                PropagatorResult[] newValues = ReplaceValues(map);
                return null == newValues ? this : new StructuralValue(newValues, m_structuralType);
            }
 
            protected PropagatorResult[] ReplaceValues(Func map)
            { 
                PropagatorResult[] newValues = new PropagatorResult[m_values.Length]; 
                bool hasChange = false;
                for (int i = 0; i < newValues.Length; i++) 
                {
                    PropagatorResult newValue = m_values[i].Replace(map);
                    if (!object.ReferenceEquals(newValue, m_values[i]))
                    { 
                        hasChange = true;
                    } 
                    newValues[i] = newValue; 
                }
                return hasChange ? newValues : null; 
            }
        }

        private class UnmodifiedStructuralValue : StructuralValue 
        {
            internal UnmodifiedStructuralValue(PropagatorResult[] values, StructuralType structuralType) 
                : base(values, structuralType) 
            {
            } 

            internal override PropagatorFlags PropagatorFlags
            {
                get 
                {
                    return PropagatorFlags.Preserve; 
                } 
            }
 
            internal override PropagatorResult Replace(Func map)
            {
                PropagatorResult[] newValues = ReplaceValues(map);
                return null == newValues ? this : new UnmodifiedStructuralValue(newValues, m_structuralType); 
            }
        } 
        #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