Propagator.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 / Propagator.cs / 1 / 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. 
        private Propagator(UpdateTranslator parent)
        { 
            // Initialize propagator state. 
            EntityUtil.CheckArgumentNull(parent, "parent");
 
            m_updateTranslator = parent;
        }
        #endregion
 
        #region Fields
        private UpdateTranslator m_updateTranslator; 
        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. 
        /// Update mapping view to propagate. 
        /// Changes in S-Space.
        static internal ChangeNode Propagate(UpdateTranslator parent, 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);
 
            // 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.ExecutePropagation(); 

            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. 
        private Propagator(UpdateTranslator parent)
        { 
            // Initialize propagator state. 
            EntityUtil.CheckArgumentNull(parent, "parent");
 
            m_updateTranslator = parent;
        }
        #endregion
 
        #region Fields
        private UpdateTranslator m_updateTranslator; 
        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. 
        /// Update mapping view to propagate. 
        /// Changes in S-Space.
        static internal ChangeNode Propagate(UpdateTranslator parent, 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);
 
            // 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.ExecutePropagation(); 

            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