TableChangeProcessor.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 / TableChangeProcessor.cs / 2 / TableChangeProcessor.cs

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

using System.Data.Metadata.Edm; 
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Common.Utils;
using System.Diagnostics; 
using System.Data.Entity;
namespace System.Data.Mapping.Update.Internal 
{ 
    /// 
    /// Processes changes applying to a table by merging inserts and deletes into updates 
    /// where appropriate.
    /// 
    /// 
    /// This class is essentially responsible for identifying inserts, deletes 
    /// and updates in a particular table based on the 
    /// produced by value propagation w.r.t. the update mapping view for that table. 
    /// Assumes the change node includes at most a single insert and at most a single delete 
    /// for a given key (where we have both, the change is treated as an update).
    ///  
    internal class TableChangeProcessor
    {
        #region Constructors
        ///  
        /// Constructs processor based on the contents of a change node.
        ///  
        /// Table for which changes are being processed. 
        internal TableChangeProcessor(EntitySet table)
        { 
            EntityUtil.CheckArgumentNull(table, "table");

            m_table = table;
 
            // cache information about table key
            m_keyOrdinals = InitializeKeyOrdinals(table); 
        } 
        #endregion
 
        #region Fields
        private readonly EntitySet m_table;
        private readonly int[] m_keyOrdinals;
        #endregion 

        #region Properties 
        ///  
        /// Gets metadata for the table being modified.
        ///  
        internal EntitySet Table
        {
            get { return m_table; }
        } 

        ///  
        /// Gets a map from column ordinal to property descriptions for columns that are components of the table's 
        /// primary key.
        ///  
        internal int[] KeyOrdinals { get { return m_keyOrdinals; } }
        #endregion

        #region Methods 
        // Determines whether the given ordinal position in the property list
        // for this table is a key value. 
        internal bool IsKeyProperty(int propertyOrdinal) 
        {
            foreach (int keyOrdinal in m_keyOrdinals) 
            {
                if (propertyOrdinal == keyOrdinal) { return true; }
            }
            return false; 
        }
 
        // Determines which column ordinals in the table are part of the key. 
        private static int[] InitializeKeyOrdinals(EntitySet table)
        { 
            EntityType tableType = table.ElementType;
            IList keyMembers = tableType.KeyMembers;
            IBaseList members = TypeHelpers.GetAllStructuralMembers(tableType);
            int[] keyOrdinals = new int[keyMembers.Count]; 

            for (int keyMemberIndex = 0; keyMemberIndex < keyMembers.Count; keyMemberIndex++) 
            { 
                EdmMember keyMember = keyMembers[keyMemberIndex];
                keyOrdinals[keyMemberIndex] = members.IndexOf(keyMember); 

                Debug.Assert(keyOrdinals[keyMemberIndex] >= 0 && keyOrdinals[keyMemberIndex] < members.Count,
                    "an EntityType key member must also be a member of the entity type");
            } 

            return keyOrdinals; 
        } 

        // Processes all insert and delete requests in the table's . Inserts 
        // and deletes with the same key are merged into updates.
        internal List CompileCommands(ChangeNode changeNode, UpdateCompiler compiler)
        {
            Set keys = new Set(compiler.m_translator.KeyComparer); 

            // Retrieve all delete results (original values) and insert results (current values) while 
            // populating a set of all row keys. The set contains a single key per row. 
            Dictionary deleteResults = ProcessKeys(compiler, changeNode.Deleted, keys);
            Dictionary insertResults = ProcessKeys(compiler, changeNode.Inserted, keys); 

            List commands = new List(deleteResults.Count + insertResults.Count);

            // Examine each row key to see if the row is being deleted, inserted or updated 
            foreach (CompositeKey key in keys)
            { 
                PropagatorResult deleteResult; 
                PropagatorResult insertResult;
 
                bool hasDelete = deleteResults.TryGetValue(key, out deleteResult);
                bool hasInsert = insertResults.TryGetValue(key, out insertResult);

                Debug.Assert(hasDelete || hasInsert, "(update/TableChangeProcessor) m_keys must not contain a value " + 
                    "if there is no corresponding insert or delete");
 
                try 
                {
                    if (!hasDelete) 
                    {
                        // this is an insert
                        commands.Add(compiler.BuildInsertCommand(insertResult, this));
                    } 
                    else if (!hasInsert)
                    { 
                        // this is a delete 
                        commands.Add(compiler.BuildDeleteCommand(deleteResult, this));
                    } 
                    else
                    {
                        // this is an update because it has both a delete result and an insert result
                        UpdateCommand updateCommand = compiler.BuildUpdateCommand(deleteResult, insertResult, this); 
                        if (null != updateCommand)
                        { 
                            // if null is returned, it means it is a no-op update 
                            commands.Add(updateCommand);
                        } 
                    }
                }
                catch (Exception e)
                { 
                    if (UpdateTranslator.RequiresContext(e))
                    { 
                        // collect state entries in scope for the current compilation 
                        List stateEntries = new List();
                        if (null != deleteResult) 
                        {
                            stateEntries.AddRange(SourceInterpreter.GetAllStateEntries(
                                deleteResult, compiler.m_translator, m_table));
                        } 
                        if (null != insertResult)
                        { 
                            stateEntries.AddRange(SourceInterpreter.GetAllStateEntries( 
                                insertResult, compiler.m_translator, m_table));
                        } 

                        throw EntityUtil.Update(System.Data.Entity.Strings.Update_GeneralExecutionException,
                            e, stateEntries);
                    } 
                    throw;
                } 
            } 

            return commands; 
        }

        // Determines key values for a list of changes. Side effect: populates  which
        // includes an entry for every key involved in a change. 
        private Dictionary ProcessKeys(UpdateCompiler compiler, List changes, Set keys)
        { 
            Dictionary map = new Dictionary( 
                compiler.m_translator.KeyComparer);
 
            foreach (PropagatorResult change in changes)
            {
                // Reassign change to row since we cannot modify iteration variable
                PropagatorResult row = change; 

                CompositeKey key = new CompositeKey(GetKeyConstants(row)); 
                map.Add(key, row); 

                keys.Add(key); 
            }

            return map;
        } 

        // Extracts key constants from the given row. 
        private PropagatorResult[] GetKeyConstants(PropagatorResult row) 
        {
            PropagatorResult[] keyConstants = new PropagatorResult[m_keyOrdinals.Length]; 
            for (int i = 0; i < m_keyOrdinals.Length; i++)
            {
                PropagatorResult constant = row.GetMemberValue(m_keyOrdinals[i]);
 
                keyConstants[i] = constant;
            } 
            return keyConstants; 
        }
        #endregion 
    }
}

// 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.Generic;
using System.Data.Common;
using System.Data.Common.Utils;
using System.Diagnostics; 
using System.Data.Entity;
namespace System.Data.Mapping.Update.Internal 
{ 
    /// 
    /// Processes changes applying to a table by merging inserts and deletes into updates 
    /// where appropriate.
    /// 
    /// 
    /// This class is essentially responsible for identifying inserts, deletes 
    /// and updates in a particular table based on the 
    /// produced by value propagation w.r.t. the update mapping view for that table. 
    /// Assumes the change node includes at most a single insert and at most a single delete 
    /// for a given key (where we have both, the change is treated as an update).
    ///  
    internal class TableChangeProcessor
    {
        #region Constructors
        ///  
        /// Constructs processor based on the contents of a change node.
        ///  
        /// Table for which changes are being processed. 
        internal TableChangeProcessor(EntitySet table)
        { 
            EntityUtil.CheckArgumentNull(table, "table");

            m_table = table;
 
            // cache information about table key
            m_keyOrdinals = InitializeKeyOrdinals(table); 
        } 
        #endregion
 
        #region Fields
        private readonly EntitySet m_table;
        private readonly int[] m_keyOrdinals;
        #endregion 

        #region Properties 
        ///  
        /// Gets metadata for the table being modified.
        ///  
        internal EntitySet Table
        {
            get { return m_table; }
        } 

        ///  
        /// Gets a map from column ordinal to property descriptions for columns that are components of the table's 
        /// primary key.
        ///  
        internal int[] KeyOrdinals { get { return m_keyOrdinals; } }
        #endregion

        #region Methods 
        // Determines whether the given ordinal position in the property list
        // for this table is a key value. 
        internal bool IsKeyProperty(int propertyOrdinal) 
        {
            foreach (int keyOrdinal in m_keyOrdinals) 
            {
                if (propertyOrdinal == keyOrdinal) { return true; }
            }
            return false; 
        }
 
        // Determines which column ordinals in the table are part of the key. 
        private static int[] InitializeKeyOrdinals(EntitySet table)
        { 
            EntityType tableType = table.ElementType;
            IList keyMembers = tableType.KeyMembers;
            IBaseList members = TypeHelpers.GetAllStructuralMembers(tableType);
            int[] keyOrdinals = new int[keyMembers.Count]; 

            for (int keyMemberIndex = 0; keyMemberIndex < keyMembers.Count; keyMemberIndex++) 
            { 
                EdmMember keyMember = keyMembers[keyMemberIndex];
                keyOrdinals[keyMemberIndex] = members.IndexOf(keyMember); 

                Debug.Assert(keyOrdinals[keyMemberIndex] >= 0 && keyOrdinals[keyMemberIndex] < members.Count,
                    "an EntityType key member must also be a member of the entity type");
            } 

            return keyOrdinals; 
        } 

        // Processes all insert and delete requests in the table's . Inserts 
        // and deletes with the same key are merged into updates.
        internal List CompileCommands(ChangeNode changeNode, UpdateCompiler compiler)
        {
            Set keys = new Set(compiler.m_translator.KeyComparer); 

            // Retrieve all delete results (original values) and insert results (current values) while 
            // populating a set of all row keys. The set contains a single key per row. 
            Dictionary deleteResults = ProcessKeys(compiler, changeNode.Deleted, keys);
            Dictionary insertResults = ProcessKeys(compiler, changeNode.Inserted, keys); 

            List commands = new List(deleteResults.Count + insertResults.Count);

            // Examine each row key to see if the row is being deleted, inserted or updated 
            foreach (CompositeKey key in keys)
            { 
                PropagatorResult deleteResult; 
                PropagatorResult insertResult;
 
                bool hasDelete = deleteResults.TryGetValue(key, out deleteResult);
                bool hasInsert = insertResults.TryGetValue(key, out insertResult);

                Debug.Assert(hasDelete || hasInsert, "(update/TableChangeProcessor) m_keys must not contain a value " + 
                    "if there is no corresponding insert or delete");
 
                try 
                {
                    if (!hasDelete) 
                    {
                        // this is an insert
                        commands.Add(compiler.BuildInsertCommand(insertResult, this));
                    } 
                    else if (!hasInsert)
                    { 
                        // this is a delete 
                        commands.Add(compiler.BuildDeleteCommand(deleteResult, this));
                    } 
                    else
                    {
                        // this is an update because it has both a delete result and an insert result
                        UpdateCommand updateCommand = compiler.BuildUpdateCommand(deleteResult, insertResult, this); 
                        if (null != updateCommand)
                        { 
                            // if null is returned, it means it is a no-op update 
                            commands.Add(updateCommand);
                        } 
                    }
                }
                catch (Exception e)
                { 
                    if (UpdateTranslator.RequiresContext(e))
                    { 
                        // collect state entries in scope for the current compilation 
                        List stateEntries = new List();
                        if (null != deleteResult) 
                        {
                            stateEntries.AddRange(SourceInterpreter.GetAllStateEntries(
                                deleteResult, compiler.m_translator, m_table));
                        } 
                        if (null != insertResult)
                        { 
                            stateEntries.AddRange(SourceInterpreter.GetAllStateEntries( 
                                insertResult, compiler.m_translator, m_table));
                        } 

                        throw EntityUtil.Update(System.Data.Entity.Strings.Update_GeneralExecutionException,
                            e, stateEntries);
                    } 
                    throw;
                } 
            } 

            return commands; 
        }

        // Determines key values for a list of changes. Side effect: populates  which
        // includes an entry for every key involved in a change. 
        private Dictionary ProcessKeys(UpdateCompiler compiler, List changes, Set keys)
        { 
            Dictionary map = new Dictionary( 
                compiler.m_translator.KeyComparer);
 
            foreach (PropagatorResult change in changes)
            {
                // Reassign change to row since we cannot modify iteration variable
                PropagatorResult row = change; 

                CompositeKey key = new CompositeKey(GetKeyConstants(row)); 
                map.Add(key, row); 

                keys.Add(key); 
            }

            return map;
        } 

        // Extracts key constants from the given row. 
        private PropagatorResult[] GetKeyConstants(PropagatorResult row) 
        {
            PropagatorResult[] keyConstants = new PropagatorResult[m_keyOrdinals.Length]; 
            for (int i = 0; i < m_keyOrdinals.Length; i++)
            {
                PropagatorResult constant = row.GetMemberValue(m_keyOrdinals[i]);
 
                keyConstants[i] = constant;
            } 
            return keyConstants; 
        }
        #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