EntityCommand.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / EntityClient / EntityCommand.cs / 4 / EntityCommand.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....], [....]
//--------------------------------------------------------------------- 
using System.Collections.Generic; 
using System.ComponentModel;
using System.Data; 
using System.Data.Common;
using System.Data.Common.EntitySql;
using System.Data.Metadata.Edm;
using System.Diagnostics; 
using System.Data.Common.QueryCache;
 
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 _esqlStatement; 
        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 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._esqlStatement = 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 
        /// 
        ///  
        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(); 
        }
 
        ///  
        /// Constructs a new EntityCommand given a EntityConnection and an EntityCommandDefition. This
        /// constructor is used by the QueryCache when dealing with ObjectQueryT 
        /// 
        /// 
        /// 
        internal EntityCommand( EntityConnection connection, EntityCommandDefinition entityCommandDefinition ) 
            : this()
        { 
            // Assign other member fields from the parameters 
            this._commandDefinition = entityCommandDefinition;
            this._parameters = new EntityParameterCollection(); 

            // Make copies of the parameters
            foreach (EntityParameter parameter in entityCommandDefinition.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();
            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._esqlStatement ?? "";
            } 
            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._esqlStatement != value) 
                {
                    this._esqlStatement = value; 

                    // Wipe out any preparation work we have done
                    Unprepare();
                } 
            }
        } 
 
#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._esqlStatement)) 
                    { 
                        // Create the parser options object, but use default options
                        ParserOptions options = new ParserOptions(); 

                        // 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._esqlStatement, perspective, options, queryParams);
                    } 
                    else
                    {
                        // We have no command text, no command tree, so throw an exception
                        throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_NoCommandText); 
                    }
                } 
                else if (CommandType.StoredProcedure == CommandType) 
                {
                    EdmFunction function = DetermineFunctionImport(); 
                    resultTree = new DbFunctionCommandTree(this.Connection.GetMetadataWorkspace(), DataSpace.CSpace, function, null);

                    // get a dictionary of names and typeusage from entity parameter collection
                    Dictionary queryParams = GetParameterTypeUsage(); 
                    foreach (KeyValuePair queryParam in queryParams)
                    { 
                        resultTree.AddParameter(queryParam.Key, queryParam.Value); 
                    }
                } 

                // 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._esqlStatement))
            {
                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(this._connection.GetMetadataWorkspace());

                // 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  [....], [....]
//--------------------------------------------------------------------- 
using System.Collections.Generic; 
using System.ComponentModel;
using System.Data; 
using System.Data.Common;
using System.Data.Common.EntitySql;
using System.Data.Metadata.Edm;
using System.Diagnostics; 
using System.Data.Common.QueryCache;
 
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 _esqlStatement; 
        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 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._esqlStatement = 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 
        /// 
        ///  
        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(); 
        }
 
        ///  
        /// Constructs a new EntityCommand given a EntityConnection and an EntityCommandDefition. This
        /// constructor is used by the QueryCache when dealing with ObjectQueryT 
        /// 
        /// 
        /// 
        internal EntityCommand( EntityConnection connection, EntityCommandDefinition entityCommandDefinition ) 
            : this()
        { 
            // Assign other member fields from the parameters 
            this._commandDefinition = entityCommandDefinition;
            this._parameters = new EntityParameterCollection(); 

            // Make copies of the parameters
            foreach (EntityParameter parameter in entityCommandDefinition.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();
            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._esqlStatement ?? "";
            } 
            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._esqlStatement != value) 
                {
                    this._esqlStatement = value; 

                    // Wipe out any preparation work we have done
                    Unprepare();
                } 
            }
        } 
 
#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._esqlStatement)) 
                    { 
                        // Create the parser options object, but use default options
                        ParserOptions options = new ParserOptions(); 

                        // 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._esqlStatement, perspective, options, queryParams);
                    } 
                    else
                    {
                        // We have no command text, no command tree, so throw an exception
                        throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_NoCommandText); 
                    }
                } 
                else if (CommandType.StoredProcedure == CommandType) 
                {
                    EdmFunction function = DetermineFunctionImport(); 
                    resultTree = new DbFunctionCommandTree(this.Connection.GetMetadataWorkspace(), DataSpace.CSpace, function, null);

                    // get a dictionary of names and typeusage from entity parameter collection
                    Dictionary queryParams = GetParameterTypeUsage(); 
                    foreach (KeyValuePair queryParam in queryParams)
                    { 
                        resultTree.AddParameter(queryParam.Key, queryParam.Value); 
                    }
                } 

                // 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._esqlStatement))
            {
                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(this._connection.GetMetadataWorkspace());

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