DynamicUpdateCommand.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Map / Update / Internal / DynamicUpdateCommand.cs / 1 / DynamicUpdateCommand.cs

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

 
using System.Collections.Generic;
using System.Data.Common.CommandTrees;
using System.Data.Metadata.Edm;
using System.Data.Common; 
using System.Data.EntityClient;
using System.Diagnostics; 
using System.Data.Common.Utils; 
using System.Linq;
namespace System.Data.Mapping.Update.Internal 
{
    internal sealed class DynamicUpdateCommand : UpdateCommand
    {
        private readonly ModificationOperator m_operator; 
        private readonly TableChangeProcessor m_processor;
        private readonly List> m_inputIdentifiers; 
        private readonly Dictionary m_outputIdentifiers; 
        private readonly DbModificationCommandTree m_modificationCommandTree;
 
        internal DynamicUpdateCommand(TableChangeProcessor processor, UpdateTranslator translator, ModificationOperator op,
            PropagatorResult originalValues, PropagatorResult currentValues, DbModificationCommandTree tree,
            Dictionary outputIdentifiers)
        { 
            m_processor = EntityUtil.CheckArgumentNull(processor, "processor");
            m_operator = op; 
            OriginalValues = originalValues; 
            CurrentValues = currentValues;
            m_modificationCommandTree = EntityUtil.CheckArgumentNull(tree, "commandTree"); 
            m_outputIdentifiers = outputIdentifiers; // may be null (not all commands have output identifiers)

            // initialize identifier information (supports lateral propagation of server gen values)
            if (ModificationOperator.Insert == op || ModificationOperator.Update == op) 
            {
                const int capacity = 2; // "average" number of identifiers per row 
                m_inputIdentifiers = new List>(capacity); 

                foreach (KeyValuePair member in 
                    Helper.PairEnumerations(TypeHelpers.GetAllStructuralMembers(CurrentValues.StructuralType),
                                             CurrentValues.GetMemberValues()))
                {
                    DbSetClause setter; 
                    long identifier = member.Value.Identifier;
 
                    if (PropagatorResult.NullIdentifier != identifier && 
                        TryGetSetterExpression(tree, member.Key, op, out setter)) // can find corresponding setter
                    { 
                        foreach (long principal in translator.KeyManager.GetPrincipals(identifier))
                        {
                            m_inputIdentifiers.Add(new KeyValuePair(principal, setter));
                        } 
                    }
                } 
            } 
        }
 
        // effects: try to find setter expression for the given member
        // requires: command tree must be an insert or update tree (since other DML trees hnabve
        private static bool TryGetSetterExpression(DbModificationCommandTree tree, EdmMember member, ModificationOperator op, out DbSetClause setter)
        { 
            Debug.Assert(op == ModificationOperator.Insert || op == ModificationOperator.Update, "only inserts and updates have setters");
            IEnumerable clauses; 
            if (ModificationOperator.Insert == op) 
            {
                clauses = ((DbInsertCommandTree)tree).SetClauses; 
            }
            else
            {
                clauses = ((DbUpdateCommandTree)tree).SetClauses; 
            }
            foreach (DbSetClause setClause in clauses) 
            { 
                // check if this is the correct setter
                if (((DbPropertyExpression)setClause.Property).Property.EdmEquals(member)) 
                {
                    setter = setClause;
                    return true;
                } 
            }
 
            // no match found 
            setter = null;
            return false; 
        }

        internal override int Execute(UpdateTranslator translator, EntityConnection connection, Dictionary identifierValues, List> generatedValues)
        { 
            // Compile command
            DbCommand command = this.CreateCommand(translator, identifierValues); 
 
            // configure command to use the connection and transaction for this session
            command.Transaction = ((null != connection.CurrentTransaction) ? connection.CurrentTransaction.StoreTransaction : null); 
            command.Connection = connection.StoreConnection;
            if (translator.CommandTimeout.HasValue)
            {
                command.CommandTimeout = translator.CommandTimeout.Value; 
            }
 
            // Execute the query 
            int rowsAffected;
            if (m_modificationCommandTree.HasReader) 
            {
                // retrieve server gen results
                rowsAffected = 0;
                using (DbDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess)) 
                {
                    if (reader.Read()) 
                    { 
                        rowsAffected++;
 
                        IBaseList members = TypeHelpers.GetAllStructuralMembers(this.CurrentValues.StructuralType);

                        for (int ordinal = 0; ordinal < reader.FieldCount; ordinal++)
                        { 
                            // column name of result corresponds to column name of table
                            string columnName = reader.GetName(ordinal); 
                            object value = reader.GetValue(ordinal); 

                            // retrieve result which includes the context for back-propagation 
                            int columnOrdinal = members.IndexOf(members[columnName]);
                            PropagatorResult result = this.CurrentValues.GetMemberValue(columnOrdinal);

                            // register for back-propagation 
                            generatedValues.Add(new KeyValuePair(result, value));
 
                            // register identifier if it exists 
                            Int64 identifier = result.Identifier;
                            if (PropagatorResult.NullIdentifier != identifier) 
                            {
                                identifierValues.Add(identifier, value);
                            }
                        } 
                    }
 
                    // Consume the current reader (and subsequent result sets) so that any errors 
                    // executing the command can be intercepted
                    CommandHelper.ConsumeReader(reader); 
                }
            }
            else
            { 
                rowsAffected = command.ExecuteNonQuery();
            } 
            return rowsAffected; 
        }
 
        /// 
        /// Gets DB command definition encapsulating store logic for this command.
        /// 
        private DbCommand CreateCommand(UpdateTranslator translator, Dictionary identifierValues) 
        {
            // check if any server gen identifiers need to be set 
            if (null != m_inputIdentifiers) 
            {
                foreach (KeyValuePair inputIdentifier in m_inputIdentifiers) 
                {
                    object value;
                    if (identifierValues.TryGetValue(inputIdentifier.Key, out value))
                    { 
                        // reset the value of the identifier
                        inputIdentifier.Value.Value = m_modificationCommandTree.CreateConstantExpression(value); 
                    } 
                }
            } 

            return translator.CreateCommand(m_modificationCommandTree);
        }
 
        /// 
        /// Gets original values for the row being modified. Set only for delete and 
        /// update operations. 
        /// 
        internal readonly PropagatorResult OriginalValues; 

        /// 
        /// Gets current values for the row being modified. Set only for update and
        /// insert operations. 
        /// 
        internal readonly PropagatorResult CurrentValues; 
 

        internal ModificationOperator Operator { get { return m_operator; } } 

        internal override EntitySet Table { get { return this.m_processor.Table; } }

        internal override IEnumerable InputIdentifiers 
        {
            get 
            { 
                if (null == m_inputIdentifiers)
                { 
                    yield break;
                }
                else
                { 
                    foreach (KeyValuePair inputIdentifier in m_inputIdentifiers)
                    { 
                        yield return inputIdentifier.Key; 
                    }
                } 
            }
        }

        internal override IEnumerable OutputIdentifiers 
        {
            get 
            { 
                if (null == m_outputIdentifiers)
                { 
                    return Enumerable.Empty();
                }
                return m_outputIdentifiers.Keys;
            } 
        }
 
        internal override UpdateCommandKind Kind 
        {
            get { return UpdateCommandKind.Dynamic; } 
        }

        internal override List GetStateEntries(UpdateTranslator translator)
        { 
            List stateEntries = new List(2);
            if (null != this.OriginalValues) 
            { 
                foreach (IEntityStateEntry stateEntry in SourceInterpreter.GetAllStateEntries(
                    this.OriginalValues, translator, this.Table)) 
                {
                    stateEntries.Add(stateEntry);
                }
            } 

            if (null != this.CurrentValues) 
            { 
                foreach (IEntityStateEntry stateEntry in SourceInterpreter.GetAllStateEntries(
                    this.CurrentValues, translator, this.Table)) 
                {
                    stateEntries.Add(stateEntry);
                }
            } 
            return stateEntries;
        } 
 
        internal override int CompareToType(UpdateCommand otherCommand)
        { 
            Debug.Assert(!object.ReferenceEquals(this, otherCommand), "caller is supposed to ensure otherCommand is different reference");

            DynamicUpdateCommand other = (DynamicUpdateCommand)otherCommand;
 
            // order by operation type
            int result = (int)this.Operator - (int)other.Operator; 
            if (0 != result) { return result; } 

            // order by Container.Table 
            result = StringComparer.Ordinal.Compare(this.m_processor.Table.Name, other.m_processor.Table.Name);
            if (0 != result) { return result; }
            result = StringComparer.Ordinal.Compare(this.m_processor.Table.EntityContainer.Name, other.m_processor.Table.EntityContainer.Name);
            if (0 != result) { return result; } 

            // order by table key 
            PropagatorResult thisResult = (this.Operator == ModificationOperator.Delete ? this.OriginalValues : this.CurrentValues); 
            PropagatorResult otherResult = (other.Operator == ModificationOperator.Delete ? other.OriginalValues : other.CurrentValues);
            for (int i = 0; i < m_processor.KeyOrdinals.Length; i++) 
            {
                int keyOrdinal = m_processor.KeyOrdinals[i];
                object thisValue = thisResult.GetMemberValue(keyOrdinal).GetSimpleValue();
                object otherValue = otherResult.GetMemberValue(keyOrdinal).GetSimpleValue(); 
                result = Comparer.Default.Compare(thisValue, otherValue);
                if (0 != result) { return result; } 
            } 

            return result; 
        }
    }
}

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

 
using System.Collections.Generic;
using System.Data.Common.CommandTrees;
using System.Data.Metadata.Edm;
using System.Data.Common; 
using System.Data.EntityClient;
using System.Diagnostics; 
using System.Data.Common.Utils; 
using System.Linq;
namespace System.Data.Mapping.Update.Internal 
{
    internal sealed class DynamicUpdateCommand : UpdateCommand
    {
        private readonly ModificationOperator m_operator; 
        private readonly TableChangeProcessor m_processor;
        private readonly List> m_inputIdentifiers; 
        private readonly Dictionary m_outputIdentifiers; 
        private readonly DbModificationCommandTree m_modificationCommandTree;
 
        internal DynamicUpdateCommand(TableChangeProcessor processor, UpdateTranslator translator, ModificationOperator op,
            PropagatorResult originalValues, PropagatorResult currentValues, DbModificationCommandTree tree,
            Dictionary outputIdentifiers)
        { 
            m_processor = EntityUtil.CheckArgumentNull(processor, "processor");
            m_operator = op; 
            OriginalValues = originalValues; 
            CurrentValues = currentValues;
            m_modificationCommandTree = EntityUtil.CheckArgumentNull(tree, "commandTree"); 
            m_outputIdentifiers = outputIdentifiers; // may be null (not all commands have output identifiers)

            // initialize identifier information (supports lateral propagation of server gen values)
            if (ModificationOperator.Insert == op || ModificationOperator.Update == op) 
            {
                const int capacity = 2; // "average" number of identifiers per row 
                m_inputIdentifiers = new List>(capacity); 

                foreach (KeyValuePair member in 
                    Helper.PairEnumerations(TypeHelpers.GetAllStructuralMembers(CurrentValues.StructuralType),
                                             CurrentValues.GetMemberValues()))
                {
                    DbSetClause setter; 
                    long identifier = member.Value.Identifier;
 
                    if (PropagatorResult.NullIdentifier != identifier && 
                        TryGetSetterExpression(tree, member.Key, op, out setter)) // can find corresponding setter
                    { 
                        foreach (long principal in translator.KeyManager.GetPrincipals(identifier))
                        {
                            m_inputIdentifiers.Add(new KeyValuePair(principal, setter));
                        } 
                    }
                } 
            } 
        }
 
        // effects: try to find setter expression for the given member
        // requires: command tree must be an insert or update tree (since other DML trees hnabve
        private static bool TryGetSetterExpression(DbModificationCommandTree tree, EdmMember member, ModificationOperator op, out DbSetClause setter)
        { 
            Debug.Assert(op == ModificationOperator.Insert || op == ModificationOperator.Update, "only inserts and updates have setters");
            IEnumerable clauses; 
            if (ModificationOperator.Insert == op) 
            {
                clauses = ((DbInsertCommandTree)tree).SetClauses; 
            }
            else
            {
                clauses = ((DbUpdateCommandTree)tree).SetClauses; 
            }
            foreach (DbSetClause setClause in clauses) 
            { 
                // check if this is the correct setter
                if (((DbPropertyExpression)setClause.Property).Property.EdmEquals(member)) 
                {
                    setter = setClause;
                    return true;
                } 
            }
 
            // no match found 
            setter = null;
            return false; 
        }

        internal override int Execute(UpdateTranslator translator, EntityConnection connection, Dictionary identifierValues, List> generatedValues)
        { 
            // Compile command
            DbCommand command = this.CreateCommand(translator, identifierValues); 
 
            // configure command to use the connection and transaction for this session
            command.Transaction = ((null != connection.CurrentTransaction) ? connection.CurrentTransaction.StoreTransaction : null); 
            command.Connection = connection.StoreConnection;
            if (translator.CommandTimeout.HasValue)
            {
                command.CommandTimeout = translator.CommandTimeout.Value; 
            }
 
            // Execute the query 
            int rowsAffected;
            if (m_modificationCommandTree.HasReader) 
            {
                // retrieve server gen results
                rowsAffected = 0;
                using (DbDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess)) 
                {
                    if (reader.Read()) 
                    { 
                        rowsAffected++;
 
                        IBaseList members = TypeHelpers.GetAllStructuralMembers(this.CurrentValues.StructuralType);

                        for (int ordinal = 0; ordinal < reader.FieldCount; ordinal++)
                        { 
                            // column name of result corresponds to column name of table
                            string columnName = reader.GetName(ordinal); 
                            object value = reader.GetValue(ordinal); 

                            // retrieve result which includes the context for back-propagation 
                            int columnOrdinal = members.IndexOf(members[columnName]);
                            PropagatorResult result = this.CurrentValues.GetMemberValue(columnOrdinal);

                            // register for back-propagation 
                            generatedValues.Add(new KeyValuePair(result, value));
 
                            // register identifier if it exists 
                            Int64 identifier = result.Identifier;
                            if (PropagatorResult.NullIdentifier != identifier) 
                            {
                                identifierValues.Add(identifier, value);
                            }
                        } 
                    }
 
                    // Consume the current reader (and subsequent result sets) so that any errors 
                    // executing the command can be intercepted
                    CommandHelper.ConsumeReader(reader); 
                }
            }
            else
            { 
                rowsAffected = command.ExecuteNonQuery();
            } 
            return rowsAffected; 
        }
 
        /// 
        /// Gets DB command definition encapsulating store logic for this command.
        /// 
        private DbCommand CreateCommand(UpdateTranslator translator, Dictionary identifierValues) 
        {
            // check if any server gen identifiers need to be set 
            if (null != m_inputIdentifiers) 
            {
                foreach (KeyValuePair inputIdentifier in m_inputIdentifiers) 
                {
                    object value;
                    if (identifierValues.TryGetValue(inputIdentifier.Key, out value))
                    { 
                        // reset the value of the identifier
                        inputIdentifier.Value.Value = m_modificationCommandTree.CreateConstantExpression(value); 
                    } 
                }
            } 

            return translator.CreateCommand(m_modificationCommandTree);
        }
 
        /// 
        /// Gets original values for the row being modified. Set only for delete and 
        /// update operations. 
        /// 
        internal readonly PropagatorResult OriginalValues; 

        /// 
        /// Gets current values for the row being modified. Set only for update and
        /// insert operations. 
        /// 
        internal readonly PropagatorResult CurrentValues; 
 

        internal ModificationOperator Operator { get { return m_operator; } } 

        internal override EntitySet Table { get { return this.m_processor.Table; } }

        internal override IEnumerable InputIdentifiers 
        {
            get 
            { 
                if (null == m_inputIdentifiers)
                { 
                    yield break;
                }
                else
                { 
                    foreach (KeyValuePair inputIdentifier in m_inputIdentifiers)
                    { 
                        yield return inputIdentifier.Key; 
                    }
                } 
            }
        }

        internal override IEnumerable OutputIdentifiers 
        {
            get 
            { 
                if (null == m_outputIdentifiers)
                { 
                    return Enumerable.Empty();
                }
                return m_outputIdentifiers.Keys;
            } 
        }
 
        internal override UpdateCommandKind Kind 
        {
            get { return UpdateCommandKind.Dynamic; } 
        }

        internal override List GetStateEntries(UpdateTranslator translator)
        { 
            List stateEntries = new List(2);
            if (null != this.OriginalValues) 
            { 
                foreach (IEntityStateEntry stateEntry in SourceInterpreter.GetAllStateEntries(
                    this.OriginalValues, translator, this.Table)) 
                {
                    stateEntries.Add(stateEntry);
                }
            } 

            if (null != this.CurrentValues) 
            { 
                foreach (IEntityStateEntry stateEntry in SourceInterpreter.GetAllStateEntries(
                    this.CurrentValues, translator, this.Table)) 
                {
                    stateEntries.Add(stateEntry);
                }
            } 
            return stateEntries;
        } 
 
        internal override int CompareToType(UpdateCommand otherCommand)
        { 
            Debug.Assert(!object.ReferenceEquals(this, otherCommand), "caller is supposed to ensure otherCommand is different reference");

            DynamicUpdateCommand other = (DynamicUpdateCommand)otherCommand;
 
            // order by operation type
            int result = (int)this.Operator - (int)other.Operator; 
            if (0 != result) { return result; } 

            // order by Container.Table 
            result = StringComparer.Ordinal.Compare(this.m_processor.Table.Name, other.m_processor.Table.Name);
            if (0 != result) { return result; }
            result = StringComparer.Ordinal.Compare(this.m_processor.Table.EntityContainer.Name, other.m_processor.Table.EntityContainer.Name);
            if (0 != result) { return result; } 

            // order by table key 
            PropagatorResult thisResult = (this.Operator == ModificationOperator.Delete ? this.OriginalValues : this.CurrentValues); 
            PropagatorResult otherResult = (other.Operator == ModificationOperator.Delete ? other.OriginalValues : other.CurrentValues);
            for (int i = 0; i < m_processor.KeyOrdinals.Length; i++) 
            {
                int keyOrdinal = m_processor.KeyOrdinals[i];
                object thisValue = thisResult.GetMemberValue(keyOrdinal).GetSimpleValue();
                object otherValue = otherResult.GetMemberValue(keyOrdinal).GetSimpleValue(); 
                result = Comparer.Default.Compare(thisValue, otherValue);
                if (0 != result) { return result; } 
            } 

            return result; 
        }
    }
}

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