Propagator.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

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

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

using System.Data.Metadata.Edm; 
using System.Data.Common.CommandTrees;
using System.Collections.Generic;
using System.Diagnostics;
using System.Data.Common.Utils; 
namespace System.Data.Mapping.Update.Internal
{ 
    ///  
    /// 
    /// Comments assume there is a map between the CDM and store. Other maps are possible, but 
    /// for simplicity, we discuss the 'from' portion of the map as the C-Space and the 'to' portion
    /// of the map as the S-Space.
    /// 
    ///  
    /// This class translates C-Space change requests into S-Space change requests given a C-Space change
    /// request, an update view loader, and a target table. It has precisely one entry 
    /// point, the static  method. It performs the translation by evaluating an update 
    /// mapping view w.r.t. change requests (propagating a change request through the view).
    ///  
    /// 
    /// 
    /// 
    /// This class implements propagation rules for the following relational operators in the update mapping 
    /// view:
    ///  
    ///  
    /// Projection
    /// Selection (filter) 
    /// Union all
    /// Inner equijoin
    /// Left outer equijoin
    ///  
    /// 
    internal partial class Propagator : UpdateExpressionVisitor 
    { 
        #region Constructors
        ///  
        /// Construct a new propagator.
        /// 
        /// UpdateTranslator supporting retrieval of changes for C-Space
        /// extents referenced in the update mapping view. 
        /// Table for which updates are being produced.
        private Propagator(UpdateTranslator parent, EntitySet table) 
        { 
            // Initialize propagator state.
            EntityUtil.CheckArgumentNull(parent, "parent"); 
            EntityUtil.CheckArgumentNull(table, "table");

            m_updateTranslator = parent;
            m_table = table; 
        }
        #endregion 
 
        #region Fields
        private readonly UpdateTranslator m_updateTranslator; 
        private readonly EntitySet m_table;
        private static readonly string s_visitorName = typeof(Propagator).FullName;
        #endregion
 
        #region Properties
        ///  
        /// Gets context for updates performed by this propagator. 
        /// 
        internal UpdateTranslator UpdateTranslator 
        {
            get { return m_updateTranslator; }
        }
 
        override protected string VisitorName
        { 
            get { return s_visitorName; } 
        }
        #endregion 

        #region Methods
        /// 
        /// Propagate changes from C-Space (contained in  to the S-Space. 
        /// 
        ///  
        /// See Walker class for an explanation of this coding pattern. 
        /// 
        /// Grouper supporting retrieval of changes for C-Space 
        /// extents referenced in the update mapping view.
        /// Table for which updates are being produced.
        /// Update mapping view to propagate.
        /// Changes in S-Space. 
        static internal ChangeNode Propagate(UpdateTranslator parent, EntitySet table, DbQueryCommandTree umView)
        { 
            // Construct a new instance of a propagator, which implements a visitor interface 
            // for expression nodes (nodes in the update mapping view) and returns changes nodes
            // (seeded by C-Space extent changes returned by the grouper). 
            DbExpressionVisitor propagator = new Propagator(parent, table);

            // Walk the update mapping view using the visitor pattern implemented in this class.
            // The update mapping view describes the S-Space table we're targeting, so the result 
            // returned for the root of view corresponds to changes propagated to the S-Space.
            return umView.Query.Accept(propagator); 
        } 

        ///  
        /// Utility method constructs a new empty change node.
        /// 
        /// Update mapping view node associated with the change.
        /// Empty change node with the appropriate type for the view node. 
        private static ChangeNode BuildChangeNode(DbExpression node)
        { 
            TypeUsage nodeType = node.ResultType; 
            TypeUsage elementType = MetadataHelper.GetElementType(nodeType);
            return new ChangeNode(elementType); 
        }

        #region Visitor implementation
 
        public override ChangeNode Visit(DbCrossJoinExpression node)
        { 
            throw EntityUtil.NotSupported(System.Data.Entity.Strings.Update_UnsupportedJoinType(node.ExpressionKind)); 
        }
 
        /// 
        /// Propagates changes across a join expression node by implementing progation rules w.r.t. inputs
        /// from the left- and right- hand sides of the join. The work is actually performed
        /// by the . 
        /// 
        /// A join expression node. 
        /// Results propagated to the given join expression node. 
        public override ChangeNode Visit(DbJoinExpression node)
        { 
            EntityUtil.CheckArgumentNull(node, "node");

            if (DbExpressionKind.InnerJoin != node.ExpressionKind && DbExpressionKind.LeftOuterJoin != node.ExpressionKind)
            { 
                throw EntityUtil.NotSupported(System.Data.Entity.Strings.Update_UnsupportedJoinType(node.ExpressionKind));
            } 
 
            // There are precisely two inputs to the join which we treat as the left and right children.
            DbExpression leftExpr = node.Left.Expression; 
            DbExpression rightExpr = node.Right.Expression;

            // Get the results of propagating changes to the left and right inputs to the join.
            ChangeNode left = Visit(leftExpr); 
            ChangeNode right = Visit(rightExpr);
 
            // Construct a new join propagator, passing in the left and right results, the actual 
            // join expression, and this parent propagator.
            JoinPropagator evaluator = new JoinPropagator(left, right, node, this); 

            // Execute propagation.
            ChangeNode result = evaluator.Propagate();
 
            return result;
        } 
 
        /// 
        /// Given the results returned for the left and right inputs to a union, propagates changes 
        /// through the union.
        ///
        /// Propagation rule (U = union node, L = left input, R = right input, D(x) = deleted rows
        /// in x, I(x) = inserted rows in x) 
        ///
        /// U = L union R 
        /// D(U) = D(L) union D(R) 
        /// I(U) = I(L) union I(R)
        ///  
        /// Union expression node in the update mapping view.
        /// Result of propagating changes to this union all node.
        public override ChangeNode Visit(DbUnionAllExpression node)
        { 
            EntityUtil.CheckArgumentNull(node, "node");
 
            // Initialize an empty change node result for the union all node 
            ChangeNode result = BuildChangeNode(node);
 
            // Retrieve result of propagating changes to the left and right children.
            ChangeNode left = Visit(node.Left);
            ChangeNode right = Visit(node.Right);
 
            // Implement insertion propagation rule I(U) = I(L) union I(R)
            result.Inserted.AddRange(left.Inserted); 
            result.Inserted.AddRange(right.Inserted); 

            // Implement deletion progation rule D(U) = D(L) union D(R) 
            result.Deleted.AddRange(left.Deleted);
            result.Deleted.AddRange(right.Deleted);

            // The choice of side for the placeholder is arbitrary, since CQTs enforce type compatibility 
            // for the left and right hand sides of the union.
            result.Placeholder = left.Placeholder; 
 
            return result;
        } 

        /// 
        /// Propagate projection.
        /// 
        /// Propagation rule (P = projection node, S = projection input, D(x) = deleted rows in x,
        /// I(x) = inserted rows in x) 
        /// 
        /// P = Proj_f S
        /// D(P) = Proj_f D(S) 
        /// I(P) = Proj_f I(S)
        /// 
        /// Projection expression node.
        /// Result of propagating changes to the projection expression node. 
        public override ChangeNode Visit(DbProjectExpression node)
        { 
            EntityUtil.CheckArgumentNull(node, "node"); 

            // Initialize an empty change node result for the projection node. 
            ChangeNode result = BuildChangeNode(node);

            // Retrieve result of propagating changes to the input of the projection.
            ChangeNode input = Visit(node.Input.Expression); 

            // Implement propagation rule for insert I(P) = Proj_f I(S) 
            foreach(PropagatorResult row in input.Inserted) 
            {
                result.Inserted.Add(Project(node, row, result.ElementType)); 
            }

            // Implement propagation rule for delete D(P) = Proj_f D(S)
            foreach(PropagatorResult row in input.Deleted) 
            {
                result.Deleted.Add(Project(node, row, result.ElementType)); 
            } 

            // Generate a placeholder for the projection node by projecting values in the 
            // placeholder for the input node.
            result.Placeholder = Project(node, input.Placeholder, result.ElementType);

            return result; 
        }
 
        ///  
        /// Performs projection for a single row. Evaluates each projection argument against the specified
        /// row, returning a result with the specified type. 
        /// 
        /// Projection expression.
        /// Row to project.
        /// Type of the projected row. 
        /// Projected row.
        private PropagatorResult Project(DbProjectExpression node, PropagatorResult row, TypeUsage resultType) 
        { 
            EntityUtil.CheckArgumentNull(node, "node");
 
            Debug.Assert(null != node.Projection, "CQT validates DbProjectExpression.Projection property");

            DbNewInstanceExpression projection = node.Projection as DbNewInstanceExpression;
 
            if (null == projection)
            { 
                throw EntityUtil.NotSupported(System.Data.Entity.Strings.Update_UnsupportedProjection(node.Projection.ExpressionKind)); 
            }
 
            // Initialize empty structure containing space for every element of the projection.
            PropagatorResult[] projectedValues = new PropagatorResult[projection.Arguments.Count];

            // Extract value from the input row for every projection argument requested. 
            for (int ordinal = 0; ordinal < projectedValues.Length; ordinal++)
            { 
                projectedValues[ordinal] = Evaluator.Evaluate(projection.Arguments[ordinal], row, this); 
            }
 
            // Return a new row containing projected values.
            PropagatorResult projectedRow = PropagatorResult.CreateStructuralValue(projectedValues, (StructuralType)resultType.EdmType, false);

            return projectedRow; 
        }
 
        ///  
        /// Propagation rule (F = filter node, S = input to filter, I(x) = rows inserted
        /// into x, D(x) = rows deleted from x, Sigma_p = filter predicate) 
        ///
        /// F = Sigma_p S
        /// D(F) = Sigma_p D(S)
        /// I(F) = Sigma_p I(S) 
        /// 
        ///  
        ///  
        public override ChangeNode Visit(DbFilterExpression node)
        { 
            EntityUtil.CheckArgumentNull(node, "node");

            // Initialize an empty change node for this filter node.
            ChangeNode result = BuildChangeNode(node); 

            // Retrieve result of propagating changes to the input of the filter. 
            ChangeNode input = Visit(node.Input.Expression); 

            // Implement insert propagation rule I(F) = Sigma_p I(S) 
            result.Inserted.AddRange(Evaluator.Filter(node.Predicate, input.Inserted, this));

            // Implement delete propagation rule D(F) = Sigma_p D(S
            result.Deleted.AddRange(Evaluator.Filter(node.Predicate, input.Deleted, this)); 

            // The placeholder for a filter node is identical to that of the input, which has an 
            // identical shape (type). 
            result.Placeholder = input.Placeholder;
 
            return result;
        }

        ///  
        /// Handles extent expressions (these are the terminal nodes in update mapping views). This handler
        /// retrieves the changes from the grouper. 
        ///  
        /// Extent expression node
        ///  
        public override ChangeNode Visit(DbScanExpression node)
        {
            EntityUtil.CheckArgumentNull(node, "node");
 
            // Gets modifications requested for this extent from the grouper.
            EntitySetBase extent = node.Target; 
            ChangeNode extentModifications = UpdateTranslator.GetExtentModifications(extent); 

            if (null == extentModifications.Placeholder) 
            {
                // Bootstrap placeholder (essentially a record for the extent populated with default values).
                extentModifications.Placeholder = ExtentPlaceholderCreator.CreatePlaceholder(extent, UpdateTranslator);
            } 

            return extentModifications; 
        } 
        #endregion
        #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.Data.Common.CommandTrees;
using System.Collections.Generic;
using System.Diagnostics;
using System.Data.Common.Utils; 
namespace System.Data.Mapping.Update.Internal
{ 
    ///  
    /// 
    /// Comments assume there is a map between the CDM and store. Other maps are possible, but 
    /// for simplicity, we discuss the 'from' portion of the map as the C-Space and the 'to' portion
    /// of the map as the S-Space.
    /// 
    ///  
    /// This class translates C-Space change requests into S-Space change requests given a C-Space change
    /// request, an update view loader, and a target table. It has precisely one entry 
    /// point, the static  method. It performs the translation by evaluating an update 
    /// mapping view w.r.t. change requests (propagating a change request through the view).
    ///  
    /// 
    /// 
    /// 
    /// This class implements propagation rules for the following relational operators in the update mapping 
    /// view:
    ///  
    ///  
    /// Projection
    /// Selection (filter) 
    /// Union all
    /// Inner equijoin
    /// Left outer equijoin
    ///  
    /// 
    internal partial class Propagator : UpdateExpressionVisitor 
    { 
        #region Constructors
        ///  
        /// Construct a new propagator.
        /// 
        /// UpdateTranslator supporting retrieval of changes for C-Space
        /// extents referenced in the update mapping view. 
        /// Table for which updates are being produced.
        private Propagator(UpdateTranslator parent, EntitySet table) 
        { 
            // Initialize propagator state.
            EntityUtil.CheckArgumentNull(parent, "parent"); 
            EntityUtil.CheckArgumentNull(table, "table");

            m_updateTranslator = parent;
            m_table = table; 
        }
        #endregion 
 
        #region Fields
        private readonly UpdateTranslator m_updateTranslator; 
        private readonly EntitySet m_table;
        private static readonly string s_visitorName = typeof(Propagator).FullName;
        #endregion
 
        #region Properties
        ///  
        /// Gets context for updates performed by this propagator. 
        /// 
        internal UpdateTranslator UpdateTranslator 
        {
            get { return m_updateTranslator; }
        }
 
        override protected string VisitorName
        { 
            get { return s_visitorName; } 
        }
        #endregion 

        #region Methods
        /// 
        /// Propagate changes from C-Space (contained in  to the S-Space. 
        /// 
        ///  
        /// See Walker class for an explanation of this coding pattern. 
        /// 
        /// Grouper supporting retrieval of changes for C-Space 
        /// extents referenced in the update mapping view.
        /// Table for which updates are being produced.
        /// Update mapping view to propagate.
        /// Changes in S-Space. 
        static internal ChangeNode Propagate(UpdateTranslator parent, EntitySet table, DbQueryCommandTree umView)
        { 
            // Construct a new instance of a propagator, which implements a visitor interface 
            // for expression nodes (nodes in the update mapping view) and returns changes nodes
            // (seeded by C-Space extent changes returned by the grouper). 
            DbExpressionVisitor propagator = new Propagator(parent, table);

            // Walk the update mapping view using the visitor pattern implemented in this class.
            // The update mapping view describes the S-Space table we're targeting, so the result 
            // returned for the root of view corresponds to changes propagated to the S-Space.
            return umView.Query.Accept(propagator); 
        } 

        ///  
        /// Utility method constructs a new empty change node.
        /// 
        /// Update mapping view node associated with the change.
        /// Empty change node with the appropriate type for the view node. 
        private static ChangeNode BuildChangeNode(DbExpression node)
        { 
            TypeUsage nodeType = node.ResultType; 
            TypeUsage elementType = MetadataHelper.GetElementType(nodeType);
            return new ChangeNode(elementType); 
        }

        #region Visitor implementation
 
        public override ChangeNode Visit(DbCrossJoinExpression node)
        { 
            throw EntityUtil.NotSupported(System.Data.Entity.Strings.Update_UnsupportedJoinType(node.ExpressionKind)); 
        }
 
        /// 
        /// Propagates changes across a join expression node by implementing progation rules w.r.t. inputs
        /// from the left- and right- hand sides of the join. The work is actually performed
        /// by the . 
        /// 
        /// A join expression node. 
        /// Results propagated to the given join expression node. 
        public override ChangeNode Visit(DbJoinExpression node)
        { 
            EntityUtil.CheckArgumentNull(node, "node");

            if (DbExpressionKind.InnerJoin != node.ExpressionKind && DbExpressionKind.LeftOuterJoin != node.ExpressionKind)
            { 
                throw EntityUtil.NotSupported(System.Data.Entity.Strings.Update_UnsupportedJoinType(node.ExpressionKind));
            } 
 
            // There are precisely two inputs to the join which we treat as the left and right children.
            DbExpression leftExpr = node.Left.Expression; 
            DbExpression rightExpr = node.Right.Expression;

            // Get the results of propagating changes to the left and right inputs to the join.
            ChangeNode left = Visit(leftExpr); 
            ChangeNode right = Visit(rightExpr);
 
            // Construct a new join propagator, passing in the left and right results, the actual 
            // join expression, and this parent propagator.
            JoinPropagator evaluator = new JoinPropagator(left, right, node, this); 

            // Execute propagation.
            ChangeNode result = evaluator.Propagate();
 
            return result;
        } 
 
        /// 
        /// Given the results returned for the left and right inputs to a union, propagates changes 
        /// through the union.
        ///
        /// Propagation rule (U = union node, L = left input, R = right input, D(x) = deleted rows
        /// in x, I(x) = inserted rows in x) 
        ///
        /// U = L union R 
        /// D(U) = D(L) union D(R) 
        /// I(U) = I(L) union I(R)
        ///  
        /// Union expression node in the update mapping view.
        /// Result of propagating changes to this union all node.
        public override ChangeNode Visit(DbUnionAllExpression node)
        { 
            EntityUtil.CheckArgumentNull(node, "node");
 
            // Initialize an empty change node result for the union all node 
            ChangeNode result = BuildChangeNode(node);
 
            // Retrieve result of propagating changes to the left and right children.
            ChangeNode left = Visit(node.Left);
            ChangeNode right = Visit(node.Right);
 
            // Implement insertion propagation rule I(U) = I(L) union I(R)
            result.Inserted.AddRange(left.Inserted); 
            result.Inserted.AddRange(right.Inserted); 

            // Implement deletion progation rule D(U) = D(L) union D(R) 
            result.Deleted.AddRange(left.Deleted);
            result.Deleted.AddRange(right.Deleted);

            // The choice of side for the placeholder is arbitrary, since CQTs enforce type compatibility 
            // for the left and right hand sides of the union.
            result.Placeholder = left.Placeholder; 
 
            return result;
        } 

        /// 
        /// Propagate projection.
        /// 
        /// Propagation rule (P = projection node, S = projection input, D(x) = deleted rows in x,
        /// I(x) = inserted rows in x) 
        /// 
        /// P = Proj_f S
        /// D(P) = Proj_f D(S) 
        /// I(P) = Proj_f I(S)
        /// 
        /// Projection expression node.
        /// Result of propagating changes to the projection expression node. 
        public override ChangeNode Visit(DbProjectExpression node)
        { 
            EntityUtil.CheckArgumentNull(node, "node"); 

            // Initialize an empty change node result for the projection node. 
            ChangeNode result = BuildChangeNode(node);

            // Retrieve result of propagating changes to the input of the projection.
            ChangeNode input = Visit(node.Input.Expression); 

            // Implement propagation rule for insert I(P) = Proj_f I(S) 
            foreach(PropagatorResult row in input.Inserted) 
            {
                result.Inserted.Add(Project(node, row, result.ElementType)); 
            }

            // Implement propagation rule for delete D(P) = Proj_f D(S)
            foreach(PropagatorResult row in input.Deleted) 
            {
                result.Deleted.Add(Project(node, row, result.ElementType)); 
            } 

            // Generate a placeholder for the projection node by projecting values in the 
            // placeholder for the input node.
            result.Placeholder = Project(node, input.Placeholder, result.ElementType);

            return result; 
        }
 
        ///  
        /// Performs projection for a single row. Evaluates each projection argument against the specified
        /// row, returning a result with the specified type. 
        /// 
        /// Projection expression.
        /// Row to project.
        /// Type of the projected row. 
        /// Projected row.
        private PropagatorResult Project(DbProjectExpression node, PropagatorResult row, TypeUsage resultType) 
        { 
            EntityUtil.CheckArgumentNull(node, "node");
 
            Debug.Assert(null != node.Projection, "CQT validates DbProjectExpression.Projection property");

            DbNewInstanceExpression projection = node.Projection as DbNewInstanceExpression;
 
            if (null == projection)
            { 
                throw EntityUtil.NotSupported(System.Data.Entity.Strings.Update_UnsupportedProjection(node.Projection.ExpressionKind)); 
            }
 
            // Initialize empty structure containing space for every element of the projection.
            PropagatorResult[] projectedValues = new PropagatorResult[projection.Arguments.Count];

            // Extract value from the input row for every projection argument requested. 
            for (int ordinal = 0; ordinal < projectedValues.Length; ordinal++)
            { 
                projectedValues[ordinal] = Evaluator.Evaluate(projection.Arguments[ordinal], row, this); 
            }
 
            // Return a new row containing projected values.
            PropagatorResult projectedRow = PropagatorResult.CreateStructuralValue(projectedValues, (StructuralType)resultType.EdmType, false);

            return projectedRow; 
        }
 
        ///  
        /// Propagation rule (F = filter node, S = input to filter, I(x) = rows inserted
        /// into x, D(x) = rows deleted from x, Sigma_p = filter predicate) 
        ///
        /// F = Sigma_p S
        /// D(F) = Sigma_p D(S)
        /// I(F) = Sigma_p I(S) 
        /// 
        ///  
        ///  
        public override ChangeNode Visit(DbFilterExpression node)
        { 
            EntityUtil.CheckArgumentNull(node, "node");

            // Initialize an empty change node for this filter node.
            ChangeNode result = BuildChangeNode(node); 

            // Retrieve result of propagating changes to the input of the filter. 
            ChangeNode input = Visit(node.Input.Expression); 

            // Implement insert propagation rule I(F) = Sigma_p I(S) 
            result.Inserted.AddRange(Evaluator.Filter(node.Predicate, input.Inserted, this));

            // Implement delete propagation rule D(F) = Sigma_p D(S
            result.Deleted.AddRange(Evaluator.Filter(node.Predicate, input.Deleted, this)); 

            // The placeholder for a filter node is identical to that of the input, which has an 
            // identical shape (type). 
            result.Placeholder = input.Placeholder;
 
            return result;
        }

        ///  
        /// Handles extent expressions (these are the terminal nodes in update mapping views). This handler
        /// retrieves the changes from the grouper. 
        ///  
        /// Extent expression node
        ///  
        public override ChangeNode Visit(DbScanExpression node)
        {
            EntityUtil.CheckArgumentNull(node, "node");
 
            // Gets modifications requested for this extent from the grouper.
            EntitySetBase extent = node.Target; 
            ChangeNode extentModifications = UpdateTranslator.GetExtentModifications(extent); 

            if (null == extentModifications.Placeholder) 
            {
                // Bootstrap placeholder (essentially a record for the extent populated with default values).
                extentModifications.Placeholder = ExtentPlaceholderCreator.CreatePlaceholder(extent, UpdateTranslator);
            } 

            return extentModifications; 
        } 
        #endregion
        #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