ELinqQueryState.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 / Objects / ELinq / ELinqQueryState.cs / 1 / ELinqQueryState.cs

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

namespace System.Data.Objects.ELinq 
{
    using System;
    using System.Collections.Generic;
    using System.Data.Common.CommandTrees; 
    using System.Data.Metadata.Edm;
    using System.Data.Objects; 
    using System.Data.Objects.ELinq; 
    using System.Data.Objects.Internal;
    using System.Diagnostics; 
    using System.Reflection;

    using CqtExpression = System.Data.Common.CommandTrees.DbExpression;
    using LinqExpression = System.Linq.Expressions.Expression; 

    ///  
    /// Models a Linq to Entities ObjectQuery 
    /// 
    internal class ELinqQueryState : ObjectQueryState 
    {
        #region Private State

        private readonly LinqExpression _expression; 
        private List _closureBindings;
 
        #endregion 

        #region Constructors 

        /// 
        /// Constructs a new ELinqQueryImplementation based on the specified Linq Expression
        /// against the specified ObjectContext. 
        /// 
        /// The element type of the implemented ObjectQuery, as a CLR type. 
        /// The ObjectContext with which the implemented ObjectQuery is associated. 
        /// The Linq Expression that defines this query.
        internal ELinqQueryState(Type elementType, ObjectContext context, LinqExpression expression) 
            : this(elementType, context, null, expression)
        {
        }
 
        /// 
        /// Constructs a new ELinqQueryImplementation based on the specified Linq Expression 
        /// against the specified ObjectContext. 
        /// 
        /// The element type of the implemented ObjectQuery, as a CLR type. 
        /// The ObjectContext with which the implemented ObjectQuery is associated.
        /// The Linq Expression that defines this query.
        /// The parameters referenced by the implemented ObjectQuery.
        protected ELinqQueryState(Type elementType, 
                                  ObjectContext context,
                                  ObjectParameterCollection parameters, 
                                  LinqExpression expression) 
            : base(elementType, context, parameters, null)
        { 
            //
            // Initialize the LINQ expression, which is passed in via
            // public APIs on ObjectQuery and must be checked here
            // (the base class performs similar checks on the ObjectContext and MergeOption arguments). 
            //
            EntityUtil.CheckArgumentNull(expression, "expression"); 
            // closure bindings and initializers are explicitly allowed to be null 

            _expression = expression; 
        }

        #endregion
 
        #region ObjectQueryState overrides
 
        protected override TypeUsage GetResultType() 
        {
            // Since this method is only called once, on demand, a full conversion pass 
            // is performed to produce the DbExpression and return its result type.
            // This does not affect any cached execution plan or closure bindings that may be present.
            ExpressionConverter converter = this.CreateExpressionConverter();
            return converter.Convert().ResultType; 
        }
 
        internal override ObjectQueryExecutionPlan GetExecutionPlan(MergeOption? forMergeOption) 
        {
            Debug.Assert(this.Span == null, "Include span specified on compiled LINQ-based ObjectQuery instead of within the expression tree?"); 

            // If this query has already been prepared, its current execution plan may no longer be valid.
            ObjectQueryExecutionPlan plan = this._cachedPlan;
            if (plan != null) 
            {
                // Was a merge option specified in the call to Execute(MergeOption) or set via ObjectQuery.MergeOption? 
                MergeOption? explicitMergeOption = GetMergeOption(forMergeOption, this.UserSpecifiedMergeOption); 

                // If a merge option was explicitly specified, and it does not match the plan's merge option, then the plan is no longer valid. 
                if(explicitMergeOption.HasValue &&
                   explicitMergeOption.Value != plan.MergeOption)
                {
                    plan = null; 
                }
                else if (this._closureBindings != null) 
                { 
                    // No merge option was specified; the plan's merge option is either the propagated merge option from a referenced query
                    // or it is the global default merge option, so the plan is considered invalid if any closure binding changed - which includes 
                    // detecting whether a merge option was changed on a referenced query.
                    bool planInvalid = false;
                    foreach (ClosureBinding binding in this._closureBindings)
                    { 
                        planInvalid |= binding.EvaluateBinding();
                    } 
 
                    if (planInvalid)
                    { 
                        plan = null;
                    }
                }
            } 

            // The plan may have been invalidated above, or this query may never have been prepared. 
            if (plan == null) 
            {
                // Metadata is required to generate the execution plan. 
                this.ObjectContext.EnsureMetadata();

                // Reset internal state
                this._closureBindings = null; 
                this.ResetParameters();
 
                // Translate LINQ expression to a DbExpression 
                ExpressionConverter converter = this.CreateExpressionConverter();
                DbExpression queryExpression = converter.Convert(); 
                DbQueryCommandTree tree = (DbQueryCommandTree)queryExpression.CommandTree;
                tree.Query = queryExpression;

                // Retrieve the new set of closure bindings from the converter 
                this._closureBindings = converter.ClosureBindings;
 
                // Determine the merge option, with the following precedence: 
                // 1. A merge option was specified explicitly as the argument to Execute(MergeOption).
                // 2. The user has set the MergeOption property on the ObjectQuery instance. 
                // 3. A merge option has been extracted from the 'root' query and propagated to the root of the expression tree.
                // 4. The global default merge option.
                MergeOption mergeOption = EnsureMergeOption(forMergeOption,
                                                            this.UserSpecifiedMergeOption, 
                                                            converter.PropagatedMergeOption);
 
                // If parameters were aggregated from referenced (non-LINQ) ObjectQuery instances then add them to the parameters collection 
                if (converter.Parameters != null && converter.Parameters.Count > 0)
                { 
                    ObjectParameterCollection currentParams = this.EnsureParameters();
                    currentParams.SetReadOnly(false);
                    foreach (ObjectParameter convertedParam in converter.Parameters)
                    { 
                        // Note that it is safe to add the parameter directly only
                        // because parameters are cloned before they are added to the 
                        // converter's parameter collection, or they came from this 
                        // instance's parameter collection in the first place.
                        currentParams.Add(convertedParam); 
                    }
                    currentParams.SetReadOnly(true);
                }
 
                plan = ObjectQueryExecutionPlan.Prepare(this.ObjectContext, tree, this.ElementType, mergeOption, converter.PropagatedSpan);
                this._cachedPlan = plan; 
            } 

            if (this.Parameters != null) 
            {
                this.Parameters.SetReadOnly(true);
            }
 
            return plan;
        } 
 
        /// 
        /// Returns a new ObjectQueryState instance with the specified navigation property path specified as an Include span. 
        /// For eLINQ queries the Include operation is modelled as a method call expression applied to the source ObectQuery,
        /// so the  property is always null on the returned instance.
        /// 
        /// The element type of the resulting query 
        /// The ObjectQuery on which Include was called; required to build the new method call expression
        /// The new Include path 
        /// A new ObjectQueryState instance that incorporates the Include path, in this case a new method call expression 
        internal override ObjectQueryState Include(ObjectQuery sourceQuery, string includePath)
        { 
            MethodInfo includeMethod = sourceQuery.GetType().GetMethod("Include", BindingFlags.Public | BindingFlags.Instance);
            Debug.Assert(includeMethod != null, "Unable to find ObjectQuery.Include method?");

            LinqExpression includeCall = LinqExpression.Call(LinqExpression.Constant(sourceQuery), includeMethod, new LinqExpression[] { LinqExpression.Constant(includePath, typeof(string)) }); 
            ObjectQueryState retState = new ELinqQueryState(this.ElementType, this.ObjectContext, includeCall);
            this.ApplySettingsTo(retState); 
            return retState; 
        }
 
        /// 
        /// eLINQ queries do not have command text. This method always returns false.
        /// 
        /// Always set to null 
        /// Always returns false
        internal override bool TryGetCommandText(out string commandText) 
        { 
            commandText = null;
            return false; 
        }

        /// 
        /// Gets the LINQ Expression that defines this query for external (of ObjectQueryState) use. 
        /// Note that the  property is used, which is overridden by compiled eLINQ
        /// queries to produce an Expression tree where parameter references have been replaced with constants. 
        ///  
        /// The LINQ expression that describes this query
        /// Always returns true 
        internal override bool TryGetExpression(out System.Linq.Expressions.Expression expression)
        {
            expression = this.Expression;
            return true; 
        }
 
        #endregion 

        internal virtual LinqExpression Expression { get { return _expression; } } 

        protected virtual ExpressionConverter CreateExpressionConverter()
        {
            DbQueryCommandTree tree = new DbQueryCommandTree(this.ObjectContext.MetadataWorkspace, DataSpace.CSpace); 
            return new ExpressionConverter(this.ObjectContext, new BindingContext(), tree, _expression, null);
        } 
 
        private void ResetParameters()
        { 
            if (this.Parameters != null)
            {
                bool wasLocked = ((ICollection)this.Parameters).IsReadOnly;
                if (wasLocked) 
                {
                    this.Parameters.SetReadOnly(false); 
                } 
                this.Parameters.Clear();
                if (wasLocked) 
                {
                    this.Parameters.SetReadOnly(true);
                }
            } 
        }
    } 
} 

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

namespace System.Data.Objects.ELinq 
{
    using System;
    using System.Collections.Generic;
    using System.Data.Common.CommandTrees; 
    using System.Data.Metadata.Edm;
    using System.Data.Objects; 
    using System.Data.Objects.ELinq; 
    using System.Data.Objects.Internal;
    using System.Diagnostics; 
    using System.Reflection;

    using CqtExpression = System.Data.Common.CommandTrees.DbExpression;
    using LinqExpression = System.Linq.Expressions.Expression; 

    ///  
    /// Models a Linq to Entities ObjectQuery 
    /// 
    internal class ELinqQueryState : ObjectQueryState 
    {
        #region Private State

        private readonly LinqExpression _expression; 
        private List _closureBindings;
 
        #endregion 

        #region Constructors 

        /// 
        /// Constructs a new ELinqQueryImplementation based on the specified Linq Expression
        /// against the specified ObjectContext. 
        /// 
        /// The element type of the implemented ObjectQuery, as a CLR type. 
        /// The ObjectContext with which the implemented ObjectQuery is associated. 
        /// The Linq Expression that defines this query.
        internal ELinqQueryState(Type elementType, ObjectContext context, LinqExpression expression) 
            : this(elementType, context, null, expression)
        {
        }
 
        /// 
        /// Constructs a new ELinqQueryImplementation based on the specified Linq Expression 
        /// against the specified ObjectContext. 
        /// 
        /// The element type of the implemented ObjectQuery, as a CLR type. 
        /// The ObjectContext with which the implemented ObjectQuery is associated.
        /// The Linq Expression that defines this query.
        /// The parameters referenced by the implemented ObjectQuery.
        protected ELinqQueryState(Type elementType, 
                                  ObjectContext context,
                                  ObjectParameterCollection parameters, 
                                  LinqExpression expression) 
            : base(elementType, context, parameters, null)
        { 
            //
            // Initialize the LINQ expression, which is passed in via
            // public APIs on ObjectQuery and must be checked here
            // (the base class performs similar checks on the ObjectContext and MergeOption arguments). 
            //
            EntityUtil.CheckArgumentNull(expression, "expression"); 
            // closure bindings and initializers are explicitly allowed to be null 

            _expression = expression; 
        }

        #endregion
 
        #region ObjectQueryState overrides
 
        protected override TypeUsage GetResultType() 
        {
            // Since this method is only called once, on demand, a full conversion pass 
            // is performed to produce the DbExpression and return its result type.
            // This does not affect any cached execution plan or closure bindings that may be present.
            ExpressionConverter converter = this.CreateExpressionConverter();
            return converter.Convert().ResultType; 
        }
 
        internal override ObjectQueryExecutionPlan GetExecutionPlan(MergeOption? forMergeOption) 
        {
            Debug.Assert(this.Span == null, "Include span specified on compiled LINQ-based ObjectQuery instead of within the expression tree?"); 

            // If this query has already been prepared, its current execution plan may no longer be valid.
            ObjectQueryExecutionPlan plan = this._cachedPlan;
            if (plan != null) 
            {
                // Was a merge option specified in the call to Execute(MergeOption) or set via ObjectQuery.MergeOption? 
                MergeOption? explicitMergeOption = GetMergeOption(forMergeOption, this.UserSpecifiedMergeOption); 

                // If a merge option was explicitly specified, and it does not match the plan's merge option, then the plan is no longer valid. 
                if(explicitMergeOption.HasValue &&
                   explicitMergeOption.Value != plan.MergeOption)
                {
                    plan = null; 
                }
                else if (this._closureBindings != null) 
                { 
                    // No merge option was specified; the plan's merge option is either the propagated merge option from a referenced query
                    // or it is the global default merge option, so the plan is considered invalid if any closure binding changed - which includes 
                    // detecting whether a merge option was changed on a referenced query.
                    bool planInvalid = false;
                    foreach (ClosureBinding binding in this._closureBindings)
                    { 
                        planInvalid |= binding.EvaluateBinding();
                    } 
 
                    if (planInvalid)
                    { 
                        plan = null;
                    }
                }
            } 

            // The plan may have been invalidated above, or this query may never have been prepared. 
            if (plan == null) 
            {
                // Metadata is required to generate the execution plan. 
                this.ObjectContext.EnsureMetadata();

                // Reset internal state
                this._closureBindings = null; 
                this.ResetParameters();
 
                // Translate LINQ expression to a DbExpression 
                ExpressionConverter converter = this.CreateExpressionConverter();
                DbExpression queryExpression = converter.Convert(); 
                DbQueryCommandTree tree = (DbQueryCommandTree)queryExpression.CommandTree;
                tree.Query = queryExpression;

                // Retrieve the new set of closure bindings from the converter 
                this._closureBindings = converter.ClosureBindings;
 
                // Determine the merge option, with the following precedence: 
                // 1. A merge option was specified explicitly as the argument to Execute(MergeOption).
                // 2. The user has set the MergeOption property on the ObjectQuery instance. 
                // 3. A merge option has been extracted from the 'root' query and propagated to the root of the expression tree.
                // 4. The global default merge option.
                MergeOption mergeOption = EnsureMergeOption(forMergeOption,
                                                            this.UserSpecifiedMergeOption, 
                                                            converter.PropagatedMergeOption);
 
                // If parameters were aggregated from referenced (non-LINQ) ObjectQuery instances then add them to the parameters collection 
                if (converter.Parameters != null && converter.Parameters.Count > 0)
                { 
                    ObjectParameterCollection currentParams = this.EnsureParameters();
                    currentParams.SetReadOnly(false);
                    foreach (ObjectParameter convertedParam in converter.Parameters)
                    { 
                        // Note that it is safe to add the parameter directly only
                        // because parameters are cloned before they are added to the 
                        // converter's parameter collection, or they came from this 
                        // instance's parameter collection in the first place.
                        currentParams.Add(convertedParam); 
                    }
                    currentParams.SetReadOnly(true);
                }
 
                plan = ObjectQueryExecutionPlan.Prepare(this.ObjectContext, tree, this.ElementType, mergeOption, converter.PropagatedSpan);
                this._cachedPlan = plan; 
            } 

            if (this.Parameters != null) 
            {
                this.Parameters.SetReadOnly(true);
            }
 
            return plan;
        } 
 
        /// 
        /// Returns a new ObjectQueryState instance with the specified navigation property path specified as an Include span. 
        /// For eLINQ queries the Include operation is modelled as a method call expression applied to the source ObectQuery,
        /// so the  property is always null on the returned instance.
        /// 
        /// The element type of the resulting query 
        /// The ObjectQuery on which Include was called; required to build the new method call expression
        /// The new Include path 
        /// A new ObjectQueryState instance that incorporates the Include path, in this case a new method call expression 
        internal override ObjectQueryState Include(ObjectQuery sourceQuery, string includePath)
        { 
            MethodInfo includeMethod = sourceQuery.GetType().GetMethod("Include", BindingFlags.Public | BindingFlags.Instance);
            Debug.Assert(includeMethod != null, "Unable to find ObjectQuery.Include method?");

            LinqExpression includeCall = LinqExpression.Call(LinqExpression.Constant(sourceQuery), includeMethod, new LinqExpression[] { LinqExpression.Constant(includePath, typeof(string)) }); 
            ObjectQueryState retState = new ELinqQueryState(this.ElementType, this.ObjectContext, includeCall);
            this.ApplySettingsTo(retState); 
            return retState; 
        }
 
        /// 
        /// eLINQ queries do not have command text. This method always returns false.
        /// 
        /// Always set to null 
        /// Always returns false
        internal override bool TryGetCommandText(out string commandText) 
        { 
            commandText = null;
            return false; 
        }

        /// 
        /// Gets the LINQ Expression that defines this query for external (of ObjectQueryState) use. 
        /// Note that the  property is used, which is overridden by compiled eLINQ
        /// queries to produce an Expression tree where parameter references have been replaced with constants. 
        ///  
        /// The LINQ expression that describes this query
        /// Always returns true 
        internal override bool TryGetExpression(out System.Linq.Expressions.Expression expression)
        {
            expression = this.Expression;
            return true; 
        }
 
        #endregion 

        internal virtual LinqExpression Expression { get { return _expression; } } 

        protected virtual ExpressionConverter CreateExpressionConverter()
        {
            DbQueryCommandTree tree = new DbQueryCommandTree(this.ObjectContext.MetadataWorkspace, DataSpace.CSpace); 
            return new ExpressionConverter(this.ObjectContext, new BindingContext(), tree, _expression, null);
        } 
 
        private void ResetParameters()
        { 
            if (this.Parameters != null)
            {
                bool wasLocked = ((ICollection)this.Parameters).IsReadOnly;
                if (wasLocked) 
                {
                    this.Parameters.SetReadOnly(false); 
                } 
                this.Parameters.Clear();
                if (wasLocked) 
                {
                    this.Parameters.SetReadOnly(true);
                }
            } 
        }
    } 
} 

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