📄 sqlitecommand.cs
字号:
/********************************************************
* ADO.NET 2.0 Data Provider for SQLite Version 3.X
* Written by Robert Simpson (robert@blackcastlesoft.com)
*
* Released to the public domain, use at your own risk!
********************************************************/
namespace System.Data.SQLite
{
using System;
using System.Data;
using System.Data.Common;
using System.Collections.Generic;
using System.ComponentModel;
/// <summary>
/// SQLite implementation of DbCommand.
/// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
[Designer("SQLite.Designer.SQLiteCommandDesigner, SQLite.Designer, Version=1.0.31.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139"), ToolboxItem(true)]
#endif
public sealed class SQLiteCommand : DbCommand, ICloneable
{
/// <summary>
/// The command text this command is based on
/// </summary>
private string _commandText;
/// <summary>
/// The connection the command is associated with
/// </summary>
private SQLiteConnection _cnn;
/// <summary>
/// Indicates whether or not a DataReader is active on the command.
/// </summary>
private SQLiteDataReader _activeReader;
/// <summary>
/// The timeout for the command, kludged because SQLite doesn't support per-command timeout values
/// </summary>
internal int _commandTimeout;
/// <summary>
/// Designer support
/// </summary>
private bool _designTimeVisible;
/// <summary>
/// Used by DbDataAdapter to determine updating behavior
/// </summary>
private UpdateRowSource _updateRowSource;
/// <summary>
/// The collection of parameters for the command
/// </summary>
private SQLiteParameterCollection _parameterCollection;
/// <summary>
/// The SQL command text, broken into individual SQL statements as they are executed
/// </summary>
internal List<SQLiteStatement> _statementList;
/// <summary>
/// Unprocessed SQL text that has not been executed
/// </summary>
internal string _remainingText;
/// <summary>
/// Transaction associated with this command
/// </summary>
private SQLiteTransaction _transaction;
///<overloads>
/// Constructs a new SQLiteCommand
/// </overloads>
/// <summary>
/// Default constructor
/// </summary>
public SQLiteCommand() :this(null, null)
{
}
/// <summary>
/// Initializes the command with the given command text
/// </summary>
/// <param name="commandText">The SQL command text</param>
public SQLiteCommand(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 SQLiteCommand(string commandText, SQLiteConnection 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 SQLiteCommand(SQLiteConnection connection)
: this(null, connection, null)
{
}
private SQLiteCommand(SQLiteCommand source) : this(source.CommandText, source.Connection, source.Transaction)
{
CommandTimeout = source.CommandTimeout;
DesignTimeVisible = source.DesignTimeVisible;
UpdatedRowSource = source.UpdatedRowSource;
foreach (SQLiteParameter param in source._parameterCollection)
{
Parameters.Add(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 SQLiteCommand(string commandText, SQLiteConnection connection, SQLiteTransaction transaction)
{
_statementList = null;
_activeReader = null;
_commandTimeout = 30;
_parameterCollection = new SQLiteParameterCollection(this);
_designTimeVisible = true;
_updateRowSource = UpdateRowSource.FirstReturnedRecord;
_transaction = null;
if (commandText != null)
CommandText = commandText;
if (connection != null)
DbConnection = connection;
if (transaction != null)
Transaction = transaction;
}
/// <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>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
// If a reader is active on this command, don't destroy it completely
if (_activeReader != null)
{
_activeReader._disposeCommand = true;
return;
}
Connection = null;
_parameterCollection.Clear();
_commandText = null;
}
/// <summary>
/// Clears and destroys all statements currently prepared
/// </summary>
internal void ClearCommands()
{
if (_activeReader != null)
_activeReader.Close();
if (_statementList == null) return;
int x = _statementList.Count;
for (int n = 0; n < x; n++)
_statementList[n].Dispose();
_statementList = null;
_parameterCollection.Unbind();
}
/// <summary>
/// Builds an array of prepared statements for each complete SQL statement in the command text
/// </summary>
internal SQLiteStatement BuildNextCommand()
{
SQLiteStatement stmt = null;
try
{
if (_statementList == null)
_remainingText = _commandText;
stmt = _cnn._sql.Prepare(_remainingText, (_statementList == null) ? null : _statementList[_statementList.Count - 1], out _remainingText);
if (stmt != null)
{
stmt._command = this;
if (_statementList == null)
_statementList = new List<SQLiteStatement>();
_statementList.Add(stmt);
_parameterCollection.MapParameters(stmt);
stmt.BindParameters();
}
return stmt;
}
catch (Exception)
{
if (stmt != null)
{
if (_statementList.Contains(stmt))
_statementList.Remove(stmt);
stmt.Dispose();
}
// If we threw an error compiling the statement, we cannot continue on so set the remaining text to null.
_remainingText = null;
throw;
}
}
internal SQLiteStatement GetStatement(int index)
{
// Haven't built any statements yet
if (_statementList == null) return BuildNextCommand();
// If we're at the last built statement and want the next unbuilt statement, then build it
if (index == _statementList.Count)
{
if (String.IsNullOrEmpty(_remainingText) == false) return BuildNextCommand();
else return null; // No more commands
}
SQLiteStatement stmt = _statementList[index];
stmt.BindParameters();
return stmt;
}
/// <summary>
/// Not implemented
/// </summary>
public override void Cancel()
{
}
/// <summary>
/// The SQL command text associated with the command
/// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
[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 override string CommandText
{
get
{
return _commandText;
}
set
{
if (_commandText == value) return;
if (_activeReader != null)
{
throw new InvalidOperationException("Cannot set CommandText while a DataReader is active");
}
ClearCommands();
_commandText = value;
if (_cnn == null) return;
}
}
/// <summary>
/// The amount of time to wait for the connection to become available before erroring out
/// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
[DefaultValue((int)30)]
#endif
public override int CommandTimeout
{
get
{
return _commandTimeout;
}
set
{
_commandTimeout = value;
}
}
/// <summary>
/// The type of the command. SQLite only supports CommandType.Text
/// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
[RefreshProperties(RefreshProperties.All), DefaultValue(CommandType.Text)]
#endif
public override CommandType CommandType
{
get
{
return CommandType.Text;
}
set
{
if (value != CommandType.Text)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -