/Core/System.Data.EffiProz/EfzCommand.cs
C# | 715 lines | 471 code | 80 blank | 164 comment | 79 complexity | 2d7fdea057d3c61a7def9d90f1855295 MD5 | raw file
- //
- // (C) Copyright 2009,2010 EffiProz Systems
- // All rights reserved.
- // NOTICE: This code has not been licensed under any public license.
- // Author: Irantha Suwandarathna (irantha@gmail.com)
- //
-
-
- /********************************************************
- * ADO.NET 2.0 Data Provider for SQLLite Version 3.X
- * Written by Robert Simpson (robert@blackcastlesoft.com)
- ********************************************************/
- #if !SILVERLIGHT
- using System.ComponentModel;
- using System.Data.Common;
- #endif
- using System.Collections.Generic;
-
-
- namespace System.Data.EffiProz
- {
- #if !PLATFORM_COMPACTFRAMEWORK && !SILVERLIGHT
- [Designer(
- "EffiProz.Designer.EfzCommandDesigner, EffiProz.Designer, Version=1.5.0.0, Culture=neutral, PublicKeyToken=9c147f7358eea142"
- ), ToolboxItem(true)]
- #endif
- public sealed class EfzCommand
- #if !SILVERLIGHT
- : DbCommand, ICloneable
- #else
- : IDisposable
- #endif
- {
- private CommandType _commandType;
-
- /// <summary>
- /// The command text this command is based on
- /// </summary>
- private string _commandText;
-
- /// <summary>
- /// The connection the command is associated with
- /// </summary>
- private EfzConnection _cnn;
-
- /// <summary>
- /// The version of the connection the command is associated with
- /// </summary>
- private long _version;
-
- /// <summary>
- /// Indicates whether or not a DataReader is active on the command.
- /// </summary>
- private WeakReference _activeReader;
-
- /// <summary>
- /// The timeout for the command, kludged because EffiProz doesn't support per-command timeout values
- /// </summary>
- private int _commandTimeout;
-
- /// <summary>
- /// Designer support
- /// </summary>
- private bool _designTimeVisible;
-
- /// <summary>
- /// Used by DbDataAdapter to determine updating behavior
- /// </summary>
- #if !SILVERLIGHT
- private UpdateRowSource _updateRowSource;
- #endif
-
- /// <summary>
- /// The collection of parameters for the command
- /// </summary>
- private readonly EfzParameterCollection _parameterCollection;
-
-
- internal EfzStatement Statement;
-
- /// <summary>
- /// Transaction associated with this command
- /// </summary>
- private EfzTransaction _transaction;
-
-
- private List<EfzException> _warnings;
- /** The maximum number of rows to generate when executing this statement. */
- public int MaxRows;
-
- public int FetchSize;
-
- public bool FetchGeneratedResults;
-
- public void SetWarnings(List<EfzException> warnings)
- {
- _warnings = warnings;
- }
-
- public List<EfzException> Warnings
- {
- get { return _warnings; }
- }
-
- ///<overloads>
- /// Constructs a new EffiProzCommand
- /// </overloads>
- /// <summary>
- /// Default constructor
- /// </summary>
- public EfzCommand()
- : this(null, null, null)
- {
- }
-
- /// <summary>
- /// Initializes the command with the given command text
- /// </summary>
- /// <param name="commandText">The SQL command text</param>
- public EfzCommand(string commandText)
- : this(commandText, null, null)
- {
- }
-
- /// <summary>
- /// Initializes the command with the given SQL command text and attach the command to the specified
- /// connection.
- /// </summary>
- /// <param name="commandText">The SQL command text</param>
- /// <param name="connection">The connection to associate with the command</param>
- public EfzCommand(string commandText, EfzConnection connection)
- : this(commandText, connection, null)
- {
- }
-
- /// <summary>
- /// Initializes the command and associates it with the specified connection.
- /// </summary>
- /// <param name="connection">The connection to associate with the command</param>
- public EfzCommand(EfzConnection connection)
- : this(null, connection, null)
- {
- }
-
- private EfzCommand(EfzCommand source)
- : this(source.CommandText, source.Connection, source.Transaction)
- {
- CommandTimeout = source.CommandTimeout;
- _commandType = source.CommandType;
- DesignTimeVisible = source.DesignTimeVisible;
- #if !SILVERLIGHT
- UpdatedRowSource = source.UpdatedRowSource;
- #endif
- FetchGeneratedResults = source.FetchGeneratedResults;
-
- foreach (EfzParameter param in source._parameterCollection)
- {
- Parameters.Add((EfzParameter) param.Clone());
- }
- }
-
- /// <summary>
- /// Initializes a command with the given SQL, connection and transaction
- /// </summary>
- /// <param name="commandText">The SQL command text</param>
- /// <param name="connection">The connection to associate with the command</param>
- /// <param name="transaction">The transaction the command should be associated with</param>
- public EfzCommand(string commandText, EfzConnection connection, EfzTransaction transaction)
- {
- _commandTimeout = 30;
- _commandType = CommandType.Text;
- _parameterCollection = new EfzParameterCollection(this);
- _designTimeVisible = true;
- #if !SILVERLIGHT
- _updateRowSource = UpdateRowSource.None;
- #endif
-
- if (commandText != null)
- CommandText = commandText;
-
- if (connection != null)
- {
- #if !SILVERLIGHT
- DbConnection = connection;
- #else
- _cnn = connection;
- #endif
- // _commandTimeout = connection.connectio;
- }
-
- if (transaction != null)
- Transaction = transaction;
-
- FetchGeneratedResults = false;
- }
-
- /// <summary>
- /// Disposes of the command and clears all member variables
- /// </summary>
- /// <param name="disposing">Whether or not the class is being explicitly or implicitly disposed</param>
-
- #if SILVERLIGHT
- public void Dispose()
- {
- Dispose(true);
- }
- #endif
- #if !SILVERLIGHT
- protected override
- #else
- internal
- #endif
- void Dispose(bool disposing)
- {
- #if !SILVERLIGHT
- base.Dispose(disposing);
- #endif
- if (disposing)
- {
- // If a reader is active on this command, don't destroy the command, instead let the reader do it
- EfzDataReader reader = null;
- if (_activeReader != null)
- {
- try
- {
- reader = _activeReader.Target as EfzDataReader;
- }
- catch (InvalidOperationException)
- {
- }
- }
-
- if (reader != null)
- {
- reader.DisposeCommand = true;
- _activeReader = null;
- return;
- }
-
- Connection = null;
- //_parameterCollection.Clear();
- //_commandText = null;
- }
- }
-
- /// <summary>
- /// Clears and destroys all statements currently prepared
- /// </summary>
- internal void ClearCommands()
- {
- if (_activeReader != null)
- {
- EfzDataReader reader = null;
- try
- {
- reader = _activeReader.Target as EfzDataReader;
- }
- catch (InvalidOperationException)
- {
- }
-
- if (reader != null)
- reader.Close();
-
- _activeReader = null;
- }
-
- if (Statement != null)
- Statement.Dispose();
-
- Statement = null;
- //_parameterCollection.Unbind();
- }
-
-
- #if !SILVERLIGHT
-
- /// <summary>
- /// Not implemented
- /// </summary>
- public override void Cancel()
- {
- throw new NotImplementedException();
- //if (_activeReader != null)
- //{
- // EfzDataReader reader = _activeReader.Target as EfzDataReader;
- // if (reader != null)
- // reader.Cancel();
- //}
- }
- #endif
-
- /// <summary>
- /// The SQL command text associated with the command
- /// </summary>
- #if !PLATFORM_COMPACTFRAMEWORK && !SILVERLIGHT
- [DefaultValue(""), RefreshProperties(RefreshProperties.All),
- Editor(
- "Microsoft.VSDesigner.Data.SQL.Design.SqlCommandTextEditor, Microsoft.VSDesigner, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
- ,
- "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
- )]
- #endif
- public
- #if !SILVERLIGHT
- override
- #endif
- string CommandText
- {
- get { return _commandText; }
- set
- {
- if (value == null)
- throw new ArgumentNullException();
- if (_commandText == value) return;
-
- if (_activeReader != null && _activeReader.IsAlive)
- {
- throw new InvalidOperationException("Cannot set CommandText while a DataReader is active");
- }
-
- ClearCommands();
- _commandText = value;
- Statement = null;
- }
- }
-
- /// <summary>
- /// The amount of time to wait for the connection to become available before erroring out
- /// </summary>
- #if !PLATFORM_COMPACTFRAMEWORK && !SILVERLIGHT
- [DefaultValue(30)]
- #endif
- public
- #if !SILVERLIGHT
- override
- #endif
- int CommandTimeout
- {
- get { return _commandTimeout; }
- set { _commandTimeout = value; }
- }
-
- /// <summary>
- /// The type of the command. EffiProz only supports CommandType.Text
- /// </summary>
- #if !PLATFORM_COMPACTFRAMEWORK && !SILVERLIGHT
- [RefreshProperties(RefreshProperties.All), DefaultValue(CommandType.Text)]
- #endif
- public
- #if !SILVERLIGHT
- override
- #endif
- CommandType CommandType
- {
- get { return _commandType; }
- set
- {
- if (value != CommandType.Text && value != CommandType.StoredProcedure)
- throw new NotSupportedException();
- _commandType = value;
- }
- }
-
- #if !SILVERLIGHT
- /// <summary>
- /// Forwards to the local CreateParameter() function
- /// </summary>
- /// <returns></returns>
- protected override DbParameter CreateDbParameter()
- {
- return CreateParameter();
- }
- #endif
-
- /// <summary>
- /// Create a new parameter
- /// </summary>
- /// <returns></returns>
- public new EfzParameter CreateParameter()
- {
- return new EfzParameter();
- }
-
- /// <summary>
- /// The connection associated with this command
- /// </summary>
- #if !PLATFORM_COMPACTFRAMEWORK && !SILVERLIGHT
- [DefaultValue((string) null),
- Editor(
- "Microsoft.VSDesigner.Data.Design.DbConnectionEditor, Microsoft.VSDesigner, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
- ,
- "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
- )]
- #endif
- public new EfzConnection Connection
- {
- get { return _cnn; }
- set
- {
- if (_activeReader != null && _activeReader.IsAlive)
- throw new InvalidOperationException("Cannot set Connection while a DataReader is active");
-
- if (_cnn != null)
- {
- ClearCommands();
- }
-
- _cnn = value;
- if (_cnn != null)
- _version = _cnn.Version;
- }
- }
-
- #if !SILVERLIGHT
- /// <summary>
- /// Forwards to the local Connection property
- /// </summary>
- protected override DbConnection DbConnection
- {
- get { return Connection; }
- set { Connection = (EfzConnection) value; }
- }
- #endif
-
- /// <summary>
- /// Returns the EffiProzDBParameterCollection for the given command
- /// </summary>
- #if !PLATFORM_COMPACTFRAMEWORK && !SILVERLIGHT
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
- #endif
- public new EfzParameterCollection Parameters
- {
- get { return _parameterCollection; }
- }
-
- /// <summary>
- /// Forwards to the local Parameters property
- /// </summary>
- #if !SILVERLIGHT
- protected override DbParameterCollection DbParameterCollection
- {
- get { return Parameters; }
- }
- #endif
-
- /// <summary>
- /// The transaction associated with this command. EffiProz only supports one transaction per connection, so this property forwards to the
- /// command's underlying connection.
- /// </summary>
- #if !PLATFORM_COMPACTFRAMEWORK && !SILVERLIGHT
- [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- #endif
- #if !SILVERLIGHT
- new
- #endif
- public EfzTransaction Transaction
- {
- get { return _transaction; }
- set
- {
- if (_cnn != null)
- {
- if (_activeReader != null && _activeReader.IsAlive)
- throw new InvalidOperationException("Cannot set Transaction while a DataReader is active");
-
- if (value != null)
- {
- if (value.Conn != _cnn)
- throw new ArgumentException("Transaction is not associated with the command's connection");
- }
- _transaction = value;
- }
- else
- {
- if (value != null) Connection = value.Connection;
- _transaction = value;
- }
- }
- }
-
- #if !SILVERLIGHT
- /// <summary>
- /// Forwards to the local Transaction property
- /// </summary>
- protected override DbTransaction DbTransaction
- {
- get { return Transaction; }
- set { Transaction = (EfzTransaction) value; }
- }
- #else
- internal EfzTransaction DbTransaction
- {
- get
- {
- return Transaction;
- }
- set
- {
- Transaction = (EfzTransaction)value;
- }
- }
- #endif
-
- /// <summary>
- /// This function ensures there are no active readers, that we have a valid connection,
- /// that the connection is open, that all statements are prepared and all parameters are assigned
- /// in preparation for allocating a data reader.
- /// </summary>
- private void InitializeForReader()
- {
- if (_activeReader != null && _activeReader.IsAlive)
- {
- //throw new InvalidOperationException("DataReader already active on this command");
- ClearDataReader();
- }
-
- if (_cnn == null)
- throw new InvalidOperationException("No connection associated with this command");
-
- if (_cnn.State != ConnectionState.Open)
- throw new InvalidOperationException("Database is not open");
-
- // If the version of the connection has changed, clear out any previous commands before starting
- if (_cnn.Version != _version)
- {
- _version = _cnn.Version;
- ClearCommands();
- }
- }
-
- /// <summary>
- /// Creates a new EffiProzDBDataReader to execute/iterate the array of EffiProz prepared statements
- /// </summary>
- /// <param name="behavior">The behavior the data reader should adopt</param>
- /// <returns>Returns a EffiProzDBDataReader object</returns>
- #if !SILVERLIGHT
- protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
- {
- return ExecuteReader(behavior);
- }
- #endif
-
- /// <summary>
- /// Overrides the default behavior to return a EffiProzDBDataReader specialization class
- /// </summary>
- /// <param name="behavior">The flags to be associated with the reader</param>
- /// <returns>A EffiProzDBDataReader</returns>
- public new EfzDataReader ExecuteReader(CommandBehavior behavior)
- {
- #if TRACE2
- long start = DateTime.Now.Ticks;
- #endif
- InitializeForReader();
-
- var rd = new EfzDataReader(this, behavior);
- _activeReader = new WeakReference(rd, false);
- #if TRACE2
- long duration = (DateTime.Now.Ticks - start) / TimeSpan.TicksPerMillisecond;
- if (duration > 0)
- {
- System.Diagnostics.Trace.WriteLine("Query : " + CommandText);
- if (_parameterCollection != null)
- for (int i = 0; i < _parameterCollection.Count; i++)
- System.Diagnostics.Trace.WriteLine("ParamName : " + _parameterCollection[i].ParameterName + " Value: " + _parameterCollection[i].Value);
- System.Diagnostics.Trace.WriteLine("Duration : " + duration);
- System.Diagnostics.Trace.WriteLine("");
- System.Diagnostics.Trace.Flush();
- }
- #endif
-
- return rd;
- }
-
-
- /// <summary>
- /// Overrides the default behavior of DbDataReader to return a specialized EffiProzDBDataReader class
- /// </summary>
- /// <returns>A EffiProzDBDataReader</returns>
- public new EfzDataReader ExecuteReader()
- {
- return ExecuteReader(CommandBehavior.Default);
- }
-
- /// <summary>
- /// Called by the EffiProzDBDataReader when the data reader is closed.
- /// </summary>
- internal void ClearDataReader()
- {
- _activeReader = null;
- }
-
- /// <summary>
- /// Execute the command and return the number of rows inserted/updated affected by it.
- /// </summary>
- /// <returns></returns>
- public
- #if !SILVERLIGHT
- override
- #endif
- int ExecuteNonQuery()
- {
- #if TRACE2
- long start = DateTime.Now.Ticks;
- #endif
- using (EfzDataReader reader = ExecuteReader(CommandBehavior.SingleRow | CommandBehavior.SingleResult))
- {
- while (reader.NextResult())
- {
- }
- #if TRACE2
- long duration = (DateTime.Now.Ticks - start) / TimeSpan.TicksPerMillisecond;
- if (duration > 0)
- {
- System.Diagnostics.Trace.WriteLine("Query : " + CommandText);
- if (_parameterCollection != null)
- for (int i = 0; i < _parameterCollection.Count; i++ )
- System.Diagnostics.Trace.WriteLine("ParamName : " + _parameterCollection[i].ParameterName+" Value: "+_parameterCollection[i].Value);
- System.Diagnostics.Trace.WriteLine("Duration : " + duration);
- System.Diagnostics.Trace.WriteLine("");
- System.Diagnostics.Trace.Flush();
- }
- #endif
- return reader.RecordsAffected;
- }
- }
-
-
- /// <summary>
- /// Execute the command and return the first column of the first row of the resultset
- /// (if present), or null if no resultset was returned.
- /// </summary>
- /// <returns>The first column of the first row of the first resultset from the query</returns>
- public
- #if !SILVERLIGHT
- override
- #endif
- object ExecuteScalar()
- {
- #if TRACE2
- long start = DateTime.Now.Ticks;
- #endif
- InitializeForReader();
-
- using (EfzDataReader reader = ExecuteReader(CommandBehavior.SingleRow | CommandBehavior.SingleResult))
- {
- #if TRACE2
- long duration = (DateTime.Now.Ticks - start) / TimeSpan.TicksPerMillisecond;
- if (duration > 0)
- {
- System.Diagnostics.Trace.WriteLine("Query : " + CommandText);
- if (_parameterCollection != null)
- for (int i = 0; i < _parameterCollection.Count; i++)
- System.Diagnostics.Trace.WriteLine("ParamName : " + _parameterCollection[i].ParameterName + " Value: " + _parameterCollection[i].Value);
- System.Diagnostics.Trace.WriteLine("Duration : " + duration);
- System.Diagnostics.Trace.WriteLine("");
- System.Diagnostics.Trace.Flush();
- }
- #endif
- if (reader.Read())
- return reader[0];
- }
- return null;
- }
-
-
- public
- #if !SILVERLIGHT
- override
- #endif
- void Prepare()
- {
- if (Statement != null)
- Statement.Dispose();
-
- Statement = new EfzStatement(this, _commandText, true);
- }
-
- /// <summary>
- /// Sets the method the EffiProzCommandBuilder uses to determine how to update inserted or updated rows in a DataTable.
- /// </summary>
- #if !SILVERLIGHT
- [DefaultValue(UpdateRowSource.None)]
- public override UpdateRowSource UpdatedRowSource
- {
- get { return _updateRowSource; }
- set { _updateRowSource = value; }
- }
- #endif
- /// <summary>
- /// Determines if the command is visible at design time. Defaults to True.
- /// </summary>
- #if !PLATFORM_COMPACTFRAMEWORK && !SILVERLIGHT
- [DesignOnly(true), Browsable(false), DefaultValue(true), EditorBrowsable(EditorBrowsableState.Never)]
- #endif
- public
- #if !SILVERLIGHT
- override
- #endif
- bool DesignTimeVisible
- {
- get { return _designTimeVisible; }
- set { _designTimeVisible = value; }
- }
-
- /// <summary>
- /// Clones a command, including all its parameters
- /// </summary>
- /// <returns>A new EffiProzCommand with the same commandtext, connection and parameters</returns>
- public object Clone()
- {
- return new EfzCommand(this);
- }
- }
- }