EntityCommand.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 / EntityClient / EntityCommand.cs / 1305376 / EntityCommand.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 
using System.Collections.Generic;
using System.ComponentModel; 
using System.Data;
using System.Data.Common;
using System.Data.Common.CommandTrees.ExpressionBuilder;
using System.Data.Common.EntitySql; 
using System.Data.Metadata.Edm;
using System.Diagnostics; 
using System.Data.Common.QueryCache; 
using System.Linq;
 
namespace System.Data.EntityClient
{
    using System.Data.Common.CommandTrees;
    using System.Data.Common.Utils; 
    using System.Data.Query.ResultAssembly;
    using System.Data.Mapping; 
    using System.Data.Entity; 

    ///  
    /// Class representing a command for the conceptual layer
    /// 
    public sealed class EntityCommand : DbCommand
    { 
        #region Fields
        private const int InvalidCloseCount = -1; 
 
        private bool _designTimeVisible;
        private string _esqlCommandText; 
        private EntityConnection _connection;
        private DbCommandTree _preparedCommandTree;
        private EntityParameterCollection _parameters;
        private int? _commandTimeout; 
        private CommandType _commandType;
        private EntityTransaction _transaction; 
        private UpdateRowSource _updatedRowSource; 
        private EntityCommandDefinition _commandDefinition;
        private bool _isCommandDefinitionBased; 
        private DbDataReader _dataReader;
        private bool _enableQueryPlanCaching;
        private DbCommand _storeProviderCommand;
        #endregion 

        ///  
        /// Constructs the EntityCommand object not yet associated to a connection object 
        /// 
        public EntityCommand() 
        {
            GC.SuppressFinalize(this);

            // Initalize the member field with proper default values 
            this._designTimeVisible = true;
            this._commandType = CommandType.Text; 
            this._updatedRowSource = UpdateRowSource.Both; 
            this._parameters = new EntityParameterCollection();
 
            // Future Enhancement: (See SQLPT #300004256) At some point it would be
            // really nice to read defaults from a global configuration, but we're not
            // doing that today.
            this._enableQueryPlanCaching = true; 
        }
 
        ///  
        /// Constructs the EntityCommand object with the given eSQL statement, but not yet associated to a connection object
        ///  
        /// The eSQL command text to execute
        public EntityCommand(string statement)
            : this()
        { 
            // Assign other member fields from the parameters
            this._esqlCommandText = statement; 
        } 

        ///  
        /// Constructs the EntityCommand object with the given eSQL statement and the connection object to use
        /// 
        /// The eSQL command text to execute
        /// The connection object 
        public EntityCommand(string statement, EntityConnection connection)
            : this(statement) 
        { 
            // Assign other member fields from the parameters
            this._connection = connection; 
        }

        /// 
        /// Constructs the EntityCommand object with the given eSQL statement and the connection object to use 
        /// 
        /// The eSQL command text to execute 
        /// The connection object 
        /// The transaction object this command executes in
        public EntityCommand(string statement, EntityConnection connection, EntityTransaction transaction) 
            : this(statement, connection)
        {
            // Assign other member fields from the parameters
            this._transaction = transaction; 
        }
 
        ///  
        /// Internal constructor used by EntityCommandDefinition
        ///  
        /// The prepared command definition that can be executed using this EntityCommand
        internal EntityCommand(EntityCommandDefinition commandDefinition)
            : this()
        { 
            // Assign other member fields from the parameters
            this._commandDefinition = commandDefinition; 
            this._parameters = new EntityParameterCollection(); 

            // Make copies of the parameters 
            foreach (EntityParameter parameter in commandDefinition.Parameters)
            {
                this._parameters.Add(parameter.Clone());
            } 

            // Reset the dirty flag that was set to true when the parameters were added so that it won't say 
            // it's dirty to start with 
            this._parameters.ResetIsDirty();
 
            // Track the fact that this command was created from and represents an already prepared command definition
            this._isCommandDefinitionBased = true;
        }
 
        /// 
        /// Constructs a new EntityCommand given a EntityConnection and an EntityCommandDefition. This 
        /// constructor is used by ObjectQueryExecution plan to execute an ObjectQuery. 
        /// 
        /// The connection against which this EntityCommand should execute 
        /// The prepared command definition that can be executed using this EntityCommand
        internal EntityCommand(EntityConnection connection, EntityCommandDefinition entityCommandDefinition )
            : this(entityCommandDefinition)
        { 
            this._connection = connection;
        } 
 
        /// 
        /// The connection object used for executing the command 
        /// 
        public new EntityConnection Connection
        {
            get 
            {
                return this._connection; 
            } 
            set
            { 
                ThrowIfDataReaderIsOpen();
                if (this._connection != value)
                {
                    if (null != this._connection) 
                    {
                        Unprepare(); 
                    } 
                    this._connection = value;
 
                    this._transaction = null;
                }
            }
        } 

        ///  
        /// The connection object used for executing the command 
        /// 
        protected override DbConnection DbConnection 
        {
            get
            {
                return this.Connection; 
            }
            set 
            { 
                this.Connection = (EntityConnection)value;
            } 
        }

        /// 
        /// The eSQL statement to execute, only one of the command tree or the command text can be set, not both 
        /// 
        public override string CommandText 
        { 
            get
            { 
#if ENTITYCOMMAND_SETTABLE_COMMANDTREE
                // EntityClient_CannotGetSetCommandText=Cannot retrieve or set the command text because the command tree was set instead of the command text.

                // If the user set the command tree previously, then we cannot retrieve the command text 
                if (this._commandTreeSetByUser != null)
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_CannotGetSetCommandText); 
#endif 
                return this._esqlCommandText ?? "";
            } 
            set
            {
                ThrowIfDataReaderIsOpen();
 
#if ENTITYCOMMAND_SETTABLE_COMMANDTREE
                // If the user set the command tree previously, then we cannot set the command text 
                if (this._commandTreeSetByUser != null) 
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_CannotGetSetCommandText);
#endif 
                if (this._esqlCommandText != value)
                {
                    this._esqlCommandText = value;
 
                    // Wipe out any preparation work we have done
                    Unprepare(); 
 
                    // If the command text has been explicitly set (even to null or empty),
                    // then this command can no longer be considered command definition-based 
                    this._isCommandDefinitionBased = false;
                }
            }
        } 

#if ENTITYCOMMAND_SETTABLE_COMMANDTREE 
        private DbCommandTree _commandTreeSetByUser; 

        ///  
        /// The command tree to execute, only one of the command tree or the command text can be set, not both
        /// 
        internal DbCommandTree CommandTree
        { 
            get
            { 
                // EntityClient_CannotGetSetCommandTree=Cannot retrieve or set the command tree because the command text was set instead of the command tree. 

                // If the user set the command text previously, then we cannot retrieve the command tree 
                if (!string.IsNullOrEmpty(this._esqlStatement))
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_CannotGetSetCommandTree);

                return this._commandTreeSetByUser; 
            }
 
            set 
            {
                ThrowIfDataReaderIsOpen(); 

                // If the user set the command text previously, then we cannot set the command tree
                if (!string.IsNullOrEmpty(this._esqlStatement))
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_CannotGetSetCommandTree); 

                // If the command type is not Text, CommandTree cannot be set 
                if (CommandType.Text != CommandType) 
                {
                    throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.CommandTreeOnStoredProcedureEntityCommand); 
                }

                if (this._commandTreeSetByUser != value)
                { 
                    this._commandTreeSetByUser = value;
 
                    // Wipe out any preparation work we have done 
                    Unprepare();
                } 
            }
        }
#endif
 
        /// 
        /// Get or set the time in seconds to wait for the command to execute 
        ///  
        public override int CommandTimeout
        { 
            get
            {
                // Returns the timeout value if it has been set
                if (this._commandTimeout != null) 
                {
                    return this._commandTimeout.Value; 
                } 

                // Create a provider command object just so we can ask the default timeout 
                if (this._connection != null && this._connection.StoreProviderFactory != null)
                {
                    DbCommand storeCommand = this._connection.StoreProviderFactory.CreateCommand();
                    if (storeCommand != null) 
                    {
                        return storeCommand.CommandTimeout; 
                    } 
                }
 
                return 0;
            }
            set
            { 
                ThrowIfDataReaderIsOpen();
                this._commandTimeout = value; 
            } 
        }
 
        /// 
        /// The type of command being executed, only applicable when the command is using an eSQL statement and not the tree
        /// 
        public override CommandType CommandType 
        {
            get 
            { 
                return this._commandType;
            } 
            set
            {
                ThrowIfDataReaderIsOpen();
 
                // For now, command type other than Text is not supported
                if (value != CommandType.Text && value != CommandType.StoredProcedure) 
                { 
                    throw EntityUtil.NotSupported(System.Data.Entity.Strings.EntityClient_UnsupportedCommandType);
                } 

                this._commandType = value;
            }
        } 

        ///  
        /// The collection of parameters for this command 
        /// 
        public new EntityParameterCollection Parameters 
        {
            get
            {
                return this._parameters; 
            }
        } 
 
        /// 
        /// The collection of parameters for this command 
        /// 
        protected override DbParameterCollection DbParameterCollection
        {
            get 
            {
                return this.Parameters; 
            } 
        }
 
        /// 
        /// The transaction object used for executing the command
        /// 
        public new EntityTransaction Transaction 
        {
            get 
            { 
                return this._transaction;   // SQLBU 496829
            } 
            set
            {
                ThrowIfDataReaderIsOpen();
                this._transaction = value; 
            }
        } 
 
        /// 
        /// The transaction that this command executes in 
        /// 
        protected override DbTransaction DbTransaction
        {
            get 
            {
                return this.Transaction; 
            } 
            set
            { 
                this.Transaction = (EntityTransaction)value;
            }
        }
 
        /// 
        /// Gets or sets how command results are applied to the DataRow when used by the Update method of a DbDataAdapter 
        ///  
        public override UpdateRowSource UpdatedRowSource
        { 
            get
            {
                return this._updatedRowSource;
            } 
            set
            { 
                ThrowIfDataReaderIsOpen(); 
                this._updatedRowSource = value;
            } 
        }

        /// 
        /// Hidden property used by the designers 
        /// 
        public override bool DesignTimeVisible 
        { 
            get
            { 
                return this._designTimeVisible;
            }
            set
            { 
                ThrowIfDataReaderIsOpen();
                this._designTimeVisible = value; 
                TypeDescriptor.Refresh(this); 
            }
        } 

        /// 
        /// Enables/Disables query plan caching for this EntityCommand
        ///  
        public bool EnablePlanCaching
        { 
            get 
            {
                return this._enableQueryPlanCaching; 
            }

            set
            { 
                ThrowIfDataReaderIsOpen();
                this._enableQueryPlanCaching = value; 
            } 
        }
 
        /// 
        /// Cancel the execution of the command
        /// 
        public override void Cancel() 
        {
        } 
 
        /// 
        /// Create and return a new parameter object representing a parameter in the eSQL statement 
        /// 
        ///
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public new EntityParameter CreateParameter() 
        {
            return new EntityParameter(); 
        } 

        ///  
        /// Create and return a new parameter object representing a parameter in the eSQL statement
        /// 
        protected override DbParameter CreateDbParameter()
        { 
            return CreateParameter();
        } 
 
        /// 
        /// Executes the command and returns a data reader for reading the results 
        /// 
        /// A data readerobject
        public new EntityDataReader ExecuteReader()
        { 
            return ExecuteReader(CommandBehavior.Default);
        } 
 
        /// 
        /// Executes the command and returns a data reader for reading the results. May only 
        /// be called on CommandType.CommandText (otherwise, use the standard Execute* methods)
        /// 
        /// The behavior to use when executing the command
        /// A data readerobject 
        /// For stored procedure commands, if called
        /// for anything but an entity collection result 
        public new EntityDataReader ExecuteReader(CommandBehavior behavior) 
        {
            Prepare(); // prepare the query first 

            EntityDataReader reader = new EntityDataReader(this, _commandDefinition.Execute(this, behavior), behavior);
            _dataReader = reader;
            return reader; 
        }
 
        ///  
        /// Executes the command and returns a data reader for reading the results
        ///  
        /// The behavior to use when executing the command
        /// A data readerobject
        protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
        { 
            return ExecuteReader(behavior);
        } 
 
        /// 
        /// Executes the command and discard any results returned from the command 
        /// 
        /// Number of rows affected
        public override int ExecuteNonQuery()
        { 
            return ExecuteScalar(reader =>
            { 
                // consume reader before checking records affected 
                CommandHelper.ConsumeReader(reader);
                return reader.RecordsAffected; 
            });
        }

        ///  
        /// Executes the command and return the first column in the first row of the result, extra results are ignored
        ///  
        /// The result in the first column in the first row 
        public override object ExecuteScalar()
        { 
            return ExecuteScalar(reader =>
            {
                object result = reader.Read() ? reader.GetValue(0) : null;
                // consume reader before retrieving parameters 
                CommandHelper.ConsumeReader(reader);
                return result; 
            }); 
        }
 
        /// 
        /// Executes a reader and retrieves a scalar value using the given resultSelector delegate
        /// 
        private T_Result ExecuteScalar(Func resultSelector) 
        {
            T_Result result; 
            using (EntityDataReader reader = ExecuteReader(CommandBehavior.SequentialAccess)) 
            {
                result = resultSelector(reader); 
            }
            return result;
        }
 
        /// 
        /// Clear out any "compile" state 
        ///  
        internal void Unprepare()
        { 
            this._commandDefinition = null;
            this._preparedCommandTree = null;

            // Clear the dirty flag on the parameters and parameter collection 
            _parameters.ResetIsDirty();
        } 
 
        /// 
        /// Creates a prepared version of this command 
        /// 
        public override void Prepare()
        {
            ThrowIfDataReaderIsOpen(); 
            CheckIfReadyToPrepare();
 
            InnerPrepare(); 
        }
 
        /// 
        /// Creates a prepared version of this command without regard to the current connection state.
        /// Called by both  and .
        ///  
        private void InnerPrepare()
        { 
            // Unprepare if the parameters have changed to force a reprepare 
            if (_parameters.IsDirty)
            { 
                Unprepare();
            }

            _commandDefinition = GetCommandDefinition(); 
            Debug.Assert(null != _commandDefinition, "_commandDefinition cannot be null");
        } 
 
        /// 
        /// Ensures we have the command tree, either the user passed us the tree, or an eSQL statement that we need to parse 
        /// 
        private void MakeCommandTree()
        {
            // We must have a connection before we come here 
            Debug.Assert(this._connection != null);
 
            // Do the work only if we don't have a command tree yet 
            if (this._preparedCommandTree == null)
            { 
                DbCommandTree resultTree = null;
#if ENTITYCOMMAND_SETTABLE_COMMANDTREE
                if (this._commandTreeSetByUser != null)
                { 
                    // Validate the tree passed in by the user before cloning it
                    this._commandTreeSetByUser.Validate(); 
                    resultTree = this._commandTreeSetByUser.Clone(); 
                }
                else 
#endif
                if (CommandType.Text == CommandType)
                {
                    if (!string.IsNullOrEmpty(this._esqlCommandText)) 
                    {
                        // The perspective to be used for the query compilation 
                        Perspective perspective = (Perspective)new ModelPerspective(_connection.GetMetadataWorkspace()); 

                        // get a dictionary of names and typeusage from entity parameter collection 
                        Dictionary queryParams = GetParameterTypeUsage();

                        resultTree = CqlQuery.Compile(
                            this._esqlCommandText, 
                            perspective,
                            null /*parser option - use default*/, 
                            queryParams.Select(paramInfo => paramInfo.Value.Parameter(paramInfo.Key))); 
                    }
                    else 
                    {
                        // We have no command text, no command tree, so throw an exception
                        if (this._isCommandDefinitionBased)
                        { 
                            // This command was based on a prepared command definition and has no command text,
                            // so reprepare is not possible. To create a new command with different parameters 
                            // requires creating a new entity command definition and calling it's CreateCommand method. 
                            throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_CannotReprepareCommandDefinitionBasedCommand);
                        } 
                        else
                        {
                            throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_NoCommandText);
                        } 
                    }
                } 
                else if (CommandType.StoredProcedure == CommandType) 
                {
                    // get a dictionary of names and typeusage from entity parameter collection 
                    IEnumerable> queryParams = GetParameterTypeUsage();
                    EdmFunction function = DetermineFunctionImport();
                    resultTree = new DbFunctionCommandTree(this.Connection.GetMetadataWorkspace(), DataSpace.CSpace, function, null, queryParams);
                } 

                // After everything is good and succeeded, assign the result to our field 
                this._preparedCommandTree = resultTree; 
            }
        } 

        // requires: this must be a StoreProcedure command
        // effects: determines the EntityContainer function import referenced by this.CommandText
        private EdmFunction DetermineFunctionImport() 
        {
            Debug.Assert(CommandType.StoredProcedure == this.CommandType); 
 
            if (string.IsNullOrEmpty(this.CommandText) ||
                string.IsNullOrEmpty(this.CommandText.Trim())) 
            {
                throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_FunctionImportEmptyCommandText);
            }
 
            MetadataWorkspace workspace = _connection.GetMetadataWorkspace();
 
            // parse the command text 
            string containerName;
            string functionImportName; 
            string defaultContainerName = null; // no default container in EntityCommand
            CommandHelper.ParseFunctionImportCommandText(this.CommandText, defaultContainerName, out containerName, out functionImportName);

            return CommandHelper.FindFunctionImport(_connection.GetMetadataWorkspace(), containerName, functionImportName); 
        }
 
        ///  
        /// Get the command definition for the command; will construct one if there is not already
        /// one constructed, which means it will prepare the command on the client. 
        /// 
        /// the command definition
        internal EntityCommandDefinition GetCommandDefinition()
        { 
            EntityCommandDefinition entityCommandDefinition = _commandDefinition;
 
            // Construct the command definition using no special options; 
            if (null == entityCommandDefinition)
            { 
                //
                // check if the _commandDefinition is in cache
                //
                if (!TryGetEntityCommandDefinitionFromQueryCache(out entityCommandDefinition)) 
                {
                    // 
                    // if not, construct the command definition using no special options; 
                    //
                    entityCommandDefinition = CreateCommandDefinition(); 
                }

                _commandDefinition = entityCommandDefinition;
            } 

            return entityCommandDefinition; 
        } 

        ///  
        /// Returns the store command text.
        /// 
        /// 
        [Browsable(false)] 
        public string ToTraceString()
        { 
            CheckConnectionPresent(); 

            InnerPrepare(); 

            EntityCommandDefinition commandDefinition = _commandDefinition;
            if (null != commandDefinition)
            { 
                return commandDefinition.ToTraceString();
            } 
            return string.Empty; 
        }
 
        /// 
        /// Gets an entitycommanddefinition from cache if a match is found for the given cache key.
        /// 
        /// out param. returns the entitycommanddefinition for a given cache key 
        /// true if a match is found in cache, false otherwise
        private bool TryGetEntityCommandDefinitionFromQueryCache( out EntityCommandDefinition entityCommandDefinition ) 
        { 
            Debug.Assert(null != _connection, "Connection must not be null at this point");
            entityCommandDefinition = null; 

            //
            // if EnableQueryCaching is false, then just return to force the CommandDefinition to be created
            // 
            if (!this._enableQueryPlanCaching || string.IsNullOrEmpty(this._esqlCommandText))
            { 
                return false; 
            }
 
            //
            // Create cache key
            //
            EntityClientCacheKey queryCacheKey = new EntityClientCacheKey(this); 

            // 
            // Try cache lookup 
            //
            QueryCacheManager queryCacheManager = _connection.GetMetadataWorkspace().GetQueryCacheManager(); 
            Debug.Assert(null != queryCacheManager,"QuerycacheManager instance cannot be null");
            if (!queryCacheManager.TryCacheLookup(queryCacheKey, out entityCommandDefinition))
            {
                // 
                // if not, construct the command definition using no special options;
                // 
                entityCommandDefinition = CreateCommandDefinition(); 

                // 
                // add to the cache
                //
                QueryCacheEntry outQueryCacheEntry = null;
                if (queryCacheManager.TryLookupAndAdd(new EntityClientCacheEntry(queryCacheKey, entityCommandDefinition), 
                                                      out outQueryCacheEntry))
                { 
                    entityCommandDefinition = (EntityCommandDefinition)outQueryCacheEntry.GetTarget(); 
                }
            } 

            Debug.Assert(null != entityCommandDefinition, "out entityCommandDefinition must not be null");

            return true; 
        }
 
        ///  
        /// Creates a commandDefinition for the command, using the options specified.
        /// 
        /// Note: This method must not be side-effecting of the command
        /// 
        /// the command definition
        private EntityCommandDefinition CreateCommandDefinition() 
        {
            MakeCommandTree(); 
            // Always check the CQT metadata against the connection metadata (internally, CQT already 
            // validates metadata consistency)
            if (!_preparedCommandTree.MetadataWorkspace.IsMetadataWorkspaceCSCompatible(this.Connection.GetMetadataWorkspace())) 
            {
                throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_CommandTreeMetadataIncompatible);
            }
            EntityCommandDefinition result = EntityProviderServices.Instance.CreateCommandDefinition(this._connection.StoreProviderFactory, this._preparedCommandTree); 
            return result;
        } 
 
        private void CheckConnectionPresent()
        { 
            if (this._connection == null)
            {
                throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_NoConnectionForCommand);
            } 
        }
 
        ///  
        /// Checking the integrity of this command object to see if it's ready to be prepared or executed
        ///  
        private void CheckIfReadyToPrepare()
        {
            // Check that we have a connection
            CheckConnectionPresent(); 

            if (this._connection.StoreProviderFactory == null || this._connection.StoreConnection == null) 
            { 
                throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_ConnectionStringNeededBeforeOperation);
            } 

            // Make sure the connection is not closed or broken
            if ((this._connection.State == ConnectionState.Closed) || (this._connection.State == ConnectionState.Broken))
            { 
                string message = System.Data.Entity.Strings.EntityClient_ExecutingOnClosedConnection(
                    this._connection.State == ConnectionState.Closed ? 
                    System.Data.Entity.Strings.EntityClient_ConnectionStateClosed : 
                    System.Data.Entity.Strings.EntityClient_ConnectionStateBroken);
                throw EntityUtil.InvalidOperation(message); 
            }
        }

        ///  
        /// Checking if the command is still tied to a data reader, if so, then the reader must still be open and we throw
        ///  
        private void ThrowIfDataReaderIsOpen() 
        {
            if (this._dataReader != null) 
            {
                throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_DataReaderIsStillOpen);
            }
        } 

        ///  
        /// Returns a dictionary of parameter name and parameter typeusage in s-space from the entity parameter 
        /// collection given by the user.
        ///  
        /// 
        internal Dictionary GetParameterTypeUsage()
        {
            Debug.Assert(null != _parameters, "_parameters must not be null"); 
            // Extract type metadata objects from the parameters to be used by CqlQuery.Compile
            Dictionary queryParams = new Dictionary(_parameters.Count); 
            foreach (EntityParameter parameter in this._parameters) 
            {
                // Validate that the parameter name has the format: A character followed by alphanumerics or 
                // underscores
                string parameterName = parameter.ParameterName;
                if (string.IsNullOrEmpty(parameterName))
                { 
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_EmptyParameterName);
                } 
 
                // Check each parameter to make sure it's an input parameter, currently EntityCommand doesn't support
                // anything else 
                if (this.CommandType == CommandType.Text && parameter.Direction != ParameterDirection.Input)
                {
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_InvalidParameterDirection(parameter.ParameterName));
                } 

                // Checking that we can deduce the type from the parameter if the type is not set 
                if (parameter.DbType == DbType.Object && (parameter.Value == null || parameter.Value is DBNull)) 
                {
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_UnknownParameterType(parameterName)); 
                }

                // Validate that the parameter has an appropriate type and value
                // Any failures in GetTypeUsage will be surfaced as exceptions to the user 
                TypeUsage typeUsage = null;
                typeUsage = parameter.GetTypeUsage(); 
 
                // Add the query parameter, add the same time detect if this parameter has the same name of a previous parameter
                try 
                {
                    queryParams.Add(parameterName, typeUsage);
                }
                catch (ArgumentException e) 
                {
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_DuplicateParameterNames(parameter.ParameterName), e); 
                } 
            }
 
            return queryParams;
        }

        ///  
        /// Call only when the reader associated with this command is closing. Copies parameter values where necessary.
        ///  
        internal void NotifyDataReaderClosing() 
        {
            // Disassociating the data reader with this command 
            this._dataReader = null;

            if (null != _storeProviderCommand)
            { 
                CommandHelper.SetEntityParameterValues(this, _storeProviderCommand);
                _storeProviderCommand = null; 
            } 
            if (null != this.OnDataReaderClosing)
            { 
                this.OnDataReaderClosing(this, new EventArgs());
            }
        }
 
        /// 
        /// Tells the EntityCommand about the underlying store provider command in case it needs to pull parameter values 
        /// when the reader is closing. 
        /// 
        internal void SetStoreProviderCommand(DbCommand storeProviderCommand) 
        {
            _storeProviderCommand = storeProviderCommand;
        }
 
        /// 
        /// Event raised when the reader is closing. 
        ///  
        internal event EventHandler OnDataReaderClosing;
    } 
}

// 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.ComponentModel; 
using System.Data;
using System.Data.Common;
using System.Data.Common.CommandTrees.ExpressionBuilder;
using System.Data.Common.EntitySql; 
using System.Data.Metadata.Edm;
using System.Diagnostics; 
using System.Data.Common.QueryCache; 
using System.Linq;
 
namespace System.Data.EntityClient
{
    using System.Data.Common.CommandTrees;
    using System.Data.Common.Utils; 
    using System.Data.Query.ResultAssembly;
    using System.Data.Mapping; 
    using System.Data.Entity; 

    ///  
    /// Class representing a command for the conceptual layer
    /// 
    public sealed class EntityCommand : DbCommand
    { 
        #region Fields
        private const int InvalidCloseCount = -1; 
 
        private bool _designTimeVisible;
        private string _esqlCommandText; 
        private EntityConnection _connection;
        private DbCommandTree _preparedCommandTree;
        private EntityParameterCollection _parameters;
        private int? _commandTimeout; 
        private CommandType _commandType;
        private EntityTransaction _transaction; 
        private UpdateRowSource _updatedRowSource; 
        private EntityCommandDefinition _commandDefinition;
        private bool _isCommandDefinitionBased; 
        private DbDataReader _dataReader;
        private bool _enableQueryPlanCaching;
        private DbCommand _storeProviderCommand;
        #endregion 

        ///  
        /// Constructs the EntityCommand object not yet associated to a connection object 
        /// 
        public EntityCommand() 
        {
            GC.SuppressFinalize(this);

            // Initalize the member field with proper default values 
            this._designTimeVisible = true;
            this._commandType = CommandType.Text; 
            this._updatedRowSource = UpdateRowSource.Both; 
            this._parameters = new EntityParameterCollection();
 
            // Future Enhancement: (See SQLPT #300004256) At some point it would be
            // really nice to read defaults from a global configuration, but we're not
            // doing that today.
            this._enableQueryPlanCaching = true; 
        }
 
        ///  
        /// Constructs the EntityCommand object with the given eSQL statement, but not yet associated to a connection object
        ///  
        /// The eSQL command text to execute
        public EntityCommand(string statement)
            : this()
        { 
            // Assign other member fields from the parameters
            this._esqlCommandText = statement; 
        } 

        ///  
        /// Constructs the EntityCommand object with the given eSQL statement and the connection object to use
        /// 
        /// The eSQL command text to execute
        /// The connection object 
        public EntityCommand(string statement, EntityConnection connection)
            : this(statement) 
        { 
            // Assign other member fields from the parameters
            this._connection = connection; 
        }

        /// 
        /// Constructs the EntityCommand object with the given eSQL statement and the connection object to use 
        /// 
        /// The eSQL command text to execute 
        /// The connection object 
        /// The transaction object this command executes in
        public EntityCommand(string statement, EntityConnection connection, EntityTransaction transaction) 
            : this(statement, connection)
        {
            // Assign other member fields from the parameters
            this._transaction = transaction; 
        }
 
        ///  
        /// Internal constructor used by EntityCommandDefinition
        ///  
        /// The prepared command definition that can be executed using this EntityCommand
        internal EntityCommand(EntityCommandDefinition commandDefinition)
            : this()
        { 
            // Assign other member fields from the parameters
            this._commandDefinition = commandDefinition; 
            this._parameters = new EntityParameterCollection(); 

            // Make copies of the parameters 
            foreach (EntityParameter parameter in commandDefinition.Parameters)
            {
                this._parameters.Add(parameter.Clone());
            } 

            // Reset the dirty flag that was set to true when the parameters were added so that it won't say 
            // it's dirty to start with 
            this._parameters.ResetIsDirty();
 
            // Track the fact that this command was created from and represents an already prepared command definition
            this._isCommandDefinitionBased = true;
        }
 
        /// 
        /// Constructs a new EntityCommand given a EntityConnection and an EntityCommandDefition. This 
        /// constructor is used by ObjectQueryExecution plan to execute an ObjectQuery. 
        /// 
        /// The connection against which this EntityCommand should execute 
        /// The prepared command definition that can be executed using this EntityCommand
        internal EntityCommand(EntityConnection connection, EntityCommandDefinition entityCommandDefinition )
            : this(entityCommandDefinition)
        { 
            this._connection = connection;
        } 
 
        /// 
        /// The connection object used for executing the command 
        /// 
        public new EntityConnection Connection
        {
            get 
            {
                return this._connection; 
            } 
            set
            { 
                ThrowIfDataReaderIsOpen();
                if (this._connection != value)
                {
                    if (null != this._connection) 
                    {
                        Unprepare(); 
                    } 
                    this._connection = value;
 
                    this._transaction = null;
                }
            }
        } 

        ///  
        /// The connection object used for executing the command 
        /// 
        protected override DbConnection DbConnection 
        {
            get
            {
                return this.Connection; 
            }
            set 
            { 
                this.Connection = (EntityConnection)value;
            } 
        }

        /// 
        /// The eSQL statement to execute, only one of the command tree or the command text can be set, not both 
        /// 
        public override string CommandText 
        { 
            get
            { 
#if ENTITYCOMMAND_SETTABLE_COMMANDTREE
                // EntityClient_CannotGetSetCommandText=Cannot retrieve or set the command text because the command tree was set instead of the command text.

                // If the user set the command tree previously, then we cannot retrieve the command text 
                if (this._commandTreeSetByUser != null)
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_CannotGetSetCommandText); 
#endif 
                return this._esqlCommandText ?? "";
            } 
            set
            {
                ThrowIfDataReaderIsOpen();
 
#if ENTITYCOMMAND_SETTABLE_COMMANDTREE
                // If the user set the command tree previously, then we cannot set the command text 
                if (this._commandTreeSetByUser != null) 
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_CannotGetSetCommandText);
#endif 
                if (this._esqlCommandText != value)
                {
                    this._esqlCommandText = value;
 
                    // Wipe out any preparation work we have done
                    Unprepare(); 
 
                    // If the command text has been explicitly set (even to null or empty),
                    // then this command can no longer be considered command definition-based 
                    this._isCommandDefinitionBased = false;
                }
            }
        } 

#if ENTITYCOMMAND_SETTABLE_COMMANDTREE 
        private DbCommandTree _commandTreeSetByUser; 

        ///  
        /// The command tree to execute, only one of the command tree or the command text can be set, not both
        /// 
        internal DbCommandTree CommandTree
        { 
            get
            { 
                // EntityClient_CannotGetSetCommandTree=Cannot retrieve or set the command tree because the command text was set instead of the command tree. 

                // If the user set the command text previously, then we cannot retrieve the command tree 
                if (!string.IsNullOrEmpty(this._esqlStatement))
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_CannotGetSetCommandTree);

                return this._commandTreeSetByUser; 
            }
 
            set 
            {
                ThrowIfDataReaderIsOpen(); 

                // If the user set the command text previously, then we cannot set the command tree
                if (!string.IsNullOrEmpty(this._esqlStatement))
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_CannotGetSetCommandTree); 

                // If the command type is not Text, CommandTree cannot be set 
                if (CommandType.Text != CommandType) 
                {
                    throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.CommandTreeOnStoredProcedureEntityCommand); 
                }

                if (this._commandTreeSetByUser != value)
                { 
                    this._commandTreeSetByUser = value;
 
                    // Wipe out any preparation work we have done 
                    Unprepare();
                } 
            }
        }
#endif
 
        /// 
        /// Get or set the time in seconds to wait for the command to execute 
        ///  
        public override int CommandTimeout
        { 
            get
            {
                // Returns the timeout value if it has been set
                if (this._commandTimeout != null) 
                {
                    return this._commandTimeout.Value; 
                } 

                // Create a provider command object just so we can ask the default timeout 
                if (this._connection != null && this._connection.StoreProviderFactory != null)
                {
                    DbCommand storeCommand = this._connection.StoreProviderFactory.CreateCommand();
                    if (storeCommand != null) 
                    {
                        return storeCommand.CommandTimeout; 
                    } 
                }
 
                return 0;
            }
            set
            { 
                ThrowIfDataReaderIsOpen();
                this._commandTimeout = value; 
            } 
        }
 
        /// 
        /// The type of command being executed, only applicable when the command is using an eSQL statement and not the tree
        /// 
        public override CommandType CommandType 
        {
            get 
            { 
                return this._commandType;
            } 
            set
            {
                ThrowIfDataReaderIsOpen();
 
                // For now, command type other than Text is not supported
                if (value != CommandType.Text && value != CommandType.StoredProcedure) 
                { 
                    throw EntityUtil.NotSupported(System.Data.Entity.Strings.EntityClient_UnsupportedCommandType);
                } 

                this._commandType = value;
            }
        } 

        ///  
        /// The collection of parameters for this command 
        /// 
        public new EntityParameterCollection Parameters 
        {
            get
            {
                return this._parameters; 
            }
        } 
 
        /// 
        /// The collection of parameters for this command 
        /// 
        protected override DbParameterCollection DbParameterCollection
        {
            get 
            {
                return this.Parameters; 
            } 
        }
 
        /// 
        /// The transaction object used for executing the command
        /// 
        public new EntityTransaction Transaction 
        {
            get 
            { 
                return this._transaction;   // SQLBU 496829
            } 
            set
            {
                ThrowIfDataReaderIsOpen();
                this._transaction = value; 
            }
        } 
 
        /// 
        /// The transaction that this command executes in 
        /// 
        protected override DbTransaction DbTransaction
        {
            get 
            {
                return this.Transaction; 
            } 
            set
            { 
                this.Transaction = (EntityTransaction)value;
            }
        }
 
        /// 
        /// Gets or sets how command results are applied to the DataRow when used by the Update method of a DbDataAdapter 
        ///  
        public override UpdateRowSource UpdatedRowSource
        { 
            get
            {
                return this._updatedRowSource;
            } 
            set
            { 
                ThrowIfDataReaderIsOpen(); 
                this._updatedRowSource = value;
            } 
        }

        /// 
        /// Hidden property used by the designers 
        /// 
        public override bool DesignTimeVisible 
        { 
            get
            { 
                return this._designTimeVisible;
            }
            set
            { 
                ThrowIfDataReaderIsOpen();
                this._designTimeVisible = value; 
                TypeDescriptor.Refresh(this); 
            }
        } 

        /// 
        /// Enables/Disables query plan caching for this EntityCommand
        ///  
        public bool EnablePlanCaching
        { 
            get 
            {
                return this._enableQueryPlanCaching; 
            }

            set
            { 
                ThrowIfDataReaderIsOpen();
                this._enableQueryPlanCaching = value; 
            } 
        }
 
        /// 
        /// Cancel the execution of the command
        /// 
        public override void Cancel() 
        {
        } 
 
        /// 
        /// Create and return a new parameter object representing a parameter in the eSQL statement 
        /// 
        ///
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public new EntityParameter CreateParameter() 
        {
            return new EntityParameter(); 
        } 

        ///  
        /// Create and return a new parameter object representing a parameter in the eSQL statement
        /// 
        protected override DbParameter CreateDbParameter()
        { 
            return CreateParameter();
        } 
 
        /// 
        /// Executes the command and returns a data reader for reading the results 
        /// 
        /// A data readerobject
        public new EntityDataReader ExecuteReader()
        { 
            return ExecuteReader(CommandBehavior.Default);
        } 
 
        /// 
        /// Executes the command and returns a data reader for reading the results. May only 
        /// be called on CommandType.CommandText (otherwise, use the standard Execute* methods)
        /// 
        /// The behavior to use when executing the command
        /// A data readerobject 
        /// For stored procedure commands, if called
        /// for anything but an entity collection result 
        public new EntityDataReader ExecuteReader(CommandBehavior behavior) 
        {
            Prepare(); // prepare the query first 

            EntityDataReader reader = new EntityDataReader(this, _commandDefinition.Execute(this, behavior), behavior);
            _dataReader = reader;
            return reader; 
        }
 
        ///  
        /// Executes the command and returns a data reader for reading the results
        ///  
        /// The behavior to use when executing the command
        /// A data readerobject
        protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
        { 
            return ExecuteReader(behavior);
        } 
 
        /// 
        /// Executes the command and discard any results returned from the command 
        /// 
        /// Number of rows affected
        public override int ExecuteNonQuery()
        { 
            return ExecuteScalar(reader =>
            { 
                // consume reader before checking records affected 
                CommandHelper.ConsumeReader(reader);
                return reader.RecordsAffected; 
            });
        }

        ///  
        /// Executes the command and return the first column in the first row of the result, extra results are ignored
        ///  
        /// The result in the first column in the first row 
        public override object ExecuteScalar()
        { 
            return ExecuteScalar(reader =>
            {
                object result = reader.Read() ? reader.GetValue(0) : null;
                // consume reader before retrieving parameters 
                CommandHelper.ConsumeReader(reader);
                return result; 
            }); 
        }
 
        /// 
        /// Executes a reader and retrieves a scalar value using the given resultSelector delegate
        /// 
        private T_Result ExecuteScalar(Func resultSelector) 
        {
            T_Result result; 
            using (EntityDataReader reader = ExecuteReader(CommandBehavior.SequentialAccess)) 
            {
                result = resultSelector(reader); 
            }
            return result;
        }
 
        /// 
        /// Clear out any "compile" state 
        ///  
        internal void Unprepare()
        { 
            this._commandDefinition = null;
            this._preparedCommandTree = null;

            // Clear the dirty flag on the parameters and parameter collection 
            _parameters.ResetIsDirty();
        } 
 
        /// 
        /// Creates a prepared version of this command 
        /// 
        public override void Prepare()
        {
            ThrowIfDataReaderIsOpen(); 
            CheckIfReadyToPrepare();
 
            InnerPrepare(); 
        }
 
        /// 
        /// Creates a prepared version of this command without regard to the current connection state.
        /// Called by both  and .
        ///  
        private void InnerPrepare()
        { 
            // Unprepare if the parameters have changed to force a reprepare 
            if (_parameters.IsDirty)
            { 
                Unprepare();
            }

            _commandDefinition = GetCommandDefinition(); 
            Debug.Assert(null != _commandDefinition, "_commandDefinition cannot be null");
        } 
 
        /// 
        /// Ensures we have the command tree, either the user passed us the tree, or an eSQL statement that we need to parse 
        /// 
        private void MakeCommandTree()
        {
            // We must have a connection before we come here 
            Debug.Assert(this._connection != null);
 
            // Do the work only if we don't have a command tree yet 
            if (this._preparedCommandTree == null)
            { 
                DbCommandTree resultTree = null;
#if ENTITYCOMMAND_SETTABLE_COMMANDTREE
                if (this._commandTreeSetByUser != null)
                { 
                    // Validate the tree passed in by the user before cloning it
                    this._commandTreeSetByUser.Validate(); 
                    resultTree = this._commandTreeSetByUser.Clone(); 
                }
                else 
#endif
                if (CommandType.Text == CommandType)
                {
                    if (!string.IsNullOrEmpty(this._esqlCommandText)) 
                    {
                        // The perspective to be used for the query compilation 
                        Perspective perspective = (Perspective)new ModelPerspective(_connection.GetMetadataWorkspace()); 

                        // get a dictionary of names and typeusage from entity parameter collection 
                        Dictionary queryParams = GetParameterTypeUsage();

                        resultTree = CqlQuery.Compile(
                            this._esqlCommandText, 
                            perspective,
                            null /*parser option - use default*/, 
                            queryParams.Select(paramInfo => paramInfo.Value.Parameter(paramInfo.Key))); 
                    }
                    else 
                    {
                        // We have no command text, no command tree, so throw an exception
                        if (this._isCommandDefinitionBased)
                        { 
                            // This command was based on a prepared command definition and has no command text,
                            // so reprepare is not possible. To create a new command with different parameters 
                            // requires creating a new entity command definition and calling it's CreateCommand method. 
                            throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_CannotReprepareCommandDefinitionBasedCommand);
                        } 
                        else
                        {
                            throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_NoCommandText);
                        } 
                    }
                } 
                else if (CommandType.StoredProcedure == CommandType) 
                {
                    // get a dictionary of names and typeusage from entity parameter collection 
                    IEnumerable> queryParams = GetParameterTypeUsage();
                    EdmFunction function = DetermineFunctionImport();
                    resultTree = new DbFunctionCommandTree(this.Connection.GetMetadataWorkspace(), DataSpace.CSpace, function, null, queryParams);
                } 

                // After everything is good and succeeded, assign the result to our field 
                this._preparedCommandTree = resultTree; 
            }
        } 

        // requires: this must be a StoreProcedure command
        // effects: determines the EntityContainer function import referenced by this.CommandText
        private EdmFunction DetermineFunctionImport() 
        {
            Debug.Assert(CommandType.StoredProcedure == this.CommandType); 
 
            if (string.IsNullOrEmpty(this.CommandText) ||
                string.IsNullOrEmpty(this.CommandText.Trim())) 
            {
                throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_FunctionImportEmptyCommandText);
            }
 
            MetadataWorkspace workspace = _connection.GetMetadataWorkspace();
 
            // parse the command text 
            string containerName;
            string functionImportName; 
            string defaultContainerName = null; // no default container in EntityCommand
            CommandHelper.ParseFunctionImportCommandText(this.CommandText, defaultContainerName, out containerName, out functionImportName);

            return CommandHelper.FindFunctionImport(_connection.GetMetadataWorkspace(), containerName, functionImportName); 
        }
 
        ///  
        /// Get the command definition for the command; will construct one if there is not already
        /// one constructed, which means it will prepare the command on the client. 
        /// 
        /// the command definition
        internal EntityCommandDefinition GetCommandDefinition()
        { 
            EntityCommandDefinition entityCommandDefinition = _commandDefinition;
 
            // Construct the command definition using no special options; 
            if (null == entityCommandDefinition)
            { 
                //
                // check if the _commandDefinition is in cache
                //
                if (!TryGetEntityCommandDefinitionFromQueryCache(out entityCommandDefinition)) 
                {
                    // 
                    // if not, construct the command definition using no special options; 
                    //
                    entityCommandDefinition = CreateCommandDefinition(); 
                }

                _commandDefinition = entityCommandDefinition;
            } 

            return entityCommandDefinition; 
        } 

        ///  
        /// Returns the store command text.
        /// 
        /// 
        [Browsable(false)] 
        public string ToTraceString()
        { 
            CheckConnectionPresent(); 

            InnerPrepare(); 

            EntityCommandDefinition commandDefinition = _commandDefinition;
            if (null != commandDefinition)
            { 
                return commandDefinition.ToTraceString();
            } 
            return string.Empty; 
        }
 
        /// 
        /// Gets an entitycommanddefinition from cache if a match is found for the given cache key.
        /// 
        /// out param. returns the entitycommanddefinition for a given cache key 
        /// true if a match is found in cache, false otherwise
        private bool TryGetEntityCommandDefinitionFromQueryCache( out EntityCommandDefinition entityCommandDefinition ) 
        { 
            Debug.Assert(null != _connection, "Connection must not be null at this point");
            entityCommandDefinition = null; 

            //
            // if EnableQueryCaching is false, then just return to force the CommandDefinition to be created
            // 
            if (!this._enableQueryPlanCaching || string.IsNullOrEmpty(this._esqlCommandText))
            { 
                return false; 
            }
 
            //
            // Create cache key
            //
            EntityClientCacheKey queryCacheKey = new EntityClientCacheKey(this); 

            // 
            // Try cache lookup 
            //
            QueryCacheManager queryCacheManager = _connection.GetMetadataWorkspace().GetQueryCacheManager(); 
            Debug.Assert(null != queryCacheManager,"QuerycacheManager instance cannot be null");
            if (!queryCacheManager.TryCacheLookup(queryCacheKey, out entityCommandDefinition))
            {
                // 
                // if not, construct the command definition using no special options;
                // 
                entityCommandDefinition = CreateCommandDefinition(); 

                // 
                // add to the cache
                //
                QueryCacheEntry outQueryCacheEntry = null;
                if (queryCacheManager.TryLookupAndAdd(new EntityClientCacheEntry(queryCacheKey, entityCommandDefinition), 
                                                      out outQueryCacheEntry))
                { 
                    entityCommandDefinition = (EntityCommandDefinition)outQueryCacheEntry.GetTarget(); 
                }
            } 

            Debug.Assert(null != entityCommandDefinition, "out entityCommandDefinition must not be null");

            return true; 
        }
 
        ///  
        /// Creates a commandDefinition for the command, using the options specified.
        /// 
        /// Note: This method must not be side-effecting of the command
        /// 
        /// the command definition
        private EntityCommandDefinition CreateCommandDefinition() 
        {
            MakeCommandTree(); 
            // Always check the CQT metadata against the connection metadata (internally, CQT already 
            // validates metadata consistency)
            if (!_preparedCommandTree.MetadataWorkspace.IsMetadataWorkspaceCSCompatible(this.Connection.GetMetadataWorkspace())) 
            {
                throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_CommandTreeMetadataIncompatible);
            }
            EntityCommandDefinition result = EntityProviderServices.Instance.CreateCommandDefinition(this._connection.StoreProviderFactory, this._preparedCommandTree); 
            return result;
        } 
 
        private void CheckConnectionPresent()
        { 
            if (this._connection == null)
            {
                throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_NoConnectionForCommand);
            } 
        }
 
        ///  
        /// Checking the integrity of this command object to see if it's ready to be prepared or executed
        ///  
        private void CheckIfReadyToPrepare()
        {
            // Check that we have a connection
            CheckConnectionPresent(); 

            if (this._connection.StoreProviderFactory == null || this._connection.StoreConnection == null) 
            { 
                throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_ConnectionStringNeededBeforeOperation);
            } 

            // Make sure the connection is not closed or broken
            if ((this._connection.State == ConnectionState.Closed) || (this._connection.State == ConnectionState.Broken))
            { 
                string message = System.Data.Entity.Strings.EntityClient_ExecutingOnClosedConnection(
                    this._connection.State == ConnectionState.Closed ? 
                    System.Data.Entity.Strings.EntityClient_ConnectionStateClosed : 
                    System.Data.Entity.Strings.EntityClient_ConnectionStateBroken);
                throw EntityUtil.InvalidOperation(message); 
            }
        }

        ///  
        /// Checking if the command is still tied to a data reader, if so, then the reader must still be open and we throw
        ///  
        private void ThrowIfDataReaderIsOpen() 
        {
            if (this._dataReader != null) 
            {
                throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_DataReaderIsStillOpen);
            }
        } 

        ///  
        /// Returns a dictionary of parameter name and parameter typeusage in s-space from the entity parameter 
        /// collection given by the user.
        ///  
        /// 
        internal Dictionary GetParameterTypeUsage()
        {
            Debug.Assert(null != _parameters, "_parameters must not be null"); 
            // Extract type metadata objects from the parameters to be used by CqlQuery.Compile
            Dictionary queryParams = new Dictionary(_parameters.Count); 
            foreach (EntityParameter parameter in this._parameters) 
            {
                // Validate that the parameter name has the format: A character followed by alphanumerics or 
                // underscores
                string parameterName = parameter.ParameterName;
                if (string.IsNullOrEmpty(parameterName))
                { 
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_EmptyParameterName);
                } 
 
                // Check each parameter to make sure it's an input parameter, currently EntityCommand doesn't support
                // anything else 
                if (this.CommandType == CommandType.Text && parameter.Direction != ParameterDirection.Input)
                {
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_InvalidParameterDirection(parameter.ParameterName));
                } 

                // Checking that we can deduce the type from the parameter if the type is not set 
                if (parameter.DbType == DbType.Object && (parameter.Value == null || parameter.Value is DBNull)) 
                {
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_UnknownParameterType(parameterName)); 
                }

                // Validate that the parameter has an appropriate type and value
                // Any failures in GetTypeUsage will be surfaced as exceptions to the user 
                TypeUsage typeUsage = null;
                typeUsage = parameter.GetTypeUsage(); 
 
                // Add the query parameter, add the same time detect if this parameter has the same name of a previous parameter
                try 
                {
                    queryParams.Add(parameterName, typeUsage);
                }
                catch (ArgumentException e) 
                {
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_DuplicateParameterNames(parameter.ParameterName), e); 
                } 
            }
 
            return queryParams;
        }

        ///  
        /// Call only when the reader associated with this command is closing. Copies parameter values where necessary.
        ///  
        internal void NotifyDataReaderClosing() 
        {
            // Disassociating the data reader with this command 
            this._dataReader = null;

            if (null != _storeProviderCommand)
            { 
                CommandHelper.SetEntityParameterValues(this, _storeProviderCommand);
                _storeProviderCommand = null; 
            } 
            if (null != this.OnDataReaderClosing)
            { 
                this.OnDataReaderClosing(this, new EventArgs());
            }
        }
 
        /// 
        /// Tells the EntityCommand about the underlying store provider command in case it needs to pull parameter values 
        /// when the reader is closing. 
        /// 
        internal void SetStoreProviderCommand(DbCommand storeProviderCommand) 
        {
            _storeProviderCommand = storeProviderCommand;
        }
 
        /// 
        /// Event raised when the reader is closing. 
        ///  
        internal event EventHandler OnDataReaderClosing;
    } 
}

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