?? sqlitedatareader.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.Globalization;
using System.Reflection;
/// <summary>
/// SQLite implementation of DbDataReader.
/// </summary>
public sealed class SQLiteDataReader : DbDataReader
{
/// <summary>
/// Underlying command this reader is attached to
/// </summary>
private SQLiteCommand _command;
/// <summary>
/// Index of the current statement in the command being processed
/// </summary>
private int _activeStatementIndex;
/// <summary>
/// Current statement being Read()
/// </summary>
private SQLiteStatement _activeStatement;
/// <summary>
/// State of the current statement being processed.
/// -1 = First Step() executed, so the first Read() will be ignored
/// 0 = Actively reading
/// 1 = Finished reading
/// 2 = Non-row-returning statement, no records
/// </summary>
private int _readingState;
/// <summary>
/// Number of records affected by the insert/update statements executed on the command
/// </summary>
private int _rowsAffected;
/// <summary>
/// Count of fields (columns) in the row-returning statement currently being processed
/// </summary>
private int _fieldCount;
/// <summary>
/// Datatypes of active fields (columns) in the current statement, used for type-restricting data
/// </summary>
private SQLiteType[] _fieldTypeArray;
/// <summary>
/// The behavior of the datareader
/// </summary>
private CommandBehavior _commandBehavior;
/// <summary>
/// If set, then dispose of the command object when the reader is finished
/// </summary>
internal bool _disposeCommand;
/// <summary>
/// Internal constructor, initializes the datareader and sets up to begin executing statements
/// </summary>
/// <param name="cmd">The SQLiteCommand this data reader is for</param>
/// <param name="behave">The expected behavior of the data reader</param>
internal SQLiteDataReader(SQLiteCommand cmd, CommandBehavior behave)
{
_command = cmd;
_commandBehavior = behave;
_activeStatementIndex = -1;
_activeStatement = null;
_rowsAffected = -1;
_fieldCount = -1;
if (_command != null)
NextResult();
}
/// <summary>
/// Closes the datareader, potentially closing the connection as well if CommandBehavior.CloseConnection was specified.
/// </summary>
public override void Close()
{
if (_command != null)
{
while (NextResult())
{
}
_command.ClearDataReader();
if (_disposeCommand)
((IDisposable)_command).Dispose();
}
// If the datareader's behavior includes closing the connection, then do so here.
if ((_commandBehavior & CommandBehavior.CloseConnection) != 0)
_command.Connection.Close();
_command = null;
_activeStatement = null;
_fieldTypeArray = null;
}
/// <summary>
/// Disposes the datareader. Calls Close() to ensure everything is cleaned up.
/// </summary>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
GC.SuppressFinalize(this);
}
/// <summary>
/// Throw an error if the datareader is closed
/// </summary>
private void CheckClosed()
{
if (_command == null)
throw new InvalidOperationException("DataReader has been closed");
}
/// <summary>
/// Throw an error if a row is not loaded
/// </summary>
private void CheckValidRow()
{
if (_readingState != 0)
throw new InvalidOperationException("No current row");
}
/// <summary>
/// Enumerator support
/// </summary>
/// <returns>Returns a DbEnumerator object.</returns>
public override Collections.IEnumerator GetEnumerator()
{
return new DbEnumerator(this);
}
/// <summary>
/// Not implemented. Returns 0
/// </summary>
public override int Depth
{
get
{
CheckClosed();
return 0;
}
}
/// <summary>
/// Returns the number of columns in the current resultset
/// </summary>
public override int FieldCount
{
get
{
CheckClosed();
return _fieldCount;
}
}
/// <summary>
/// SQLite is inherently un-typed. All datatypes in SQLite are natively strings. The definition of the columns of a table
/// and the affinity of returned types are all we have to go on to type-restrict data in the reader.
///
/// This function attempts to verify that the type of data being requested of a column matches the datatype of the column. In
/// the case of columns that are not backed into a table definition, we attempt to match up the affinity of a column (int, double, string or blob)
/// to a set of known types that closely match that affinity. It's not an exact science, but its the best we can do.
/// </summary>
/// <returns>
/// This function throws an InvalidTypeCast() exception if the requested type doesn't match the column's definition or affinity.
/// </returns>
/// <param name="i">The index of the column to type-check</param>
/// <param name="typ">The type we want to get out of the column</param>
private TypeAffinity VerifyType(int i, DbType typ)
{
CheckClosed();
CheckValidRow();
TypeAffinity affinity = _activeStatement._sql.ColumnAffinity(_activeStatement, i);
switch (affinity)
{
case TypeAffinity.Int64:
if (typ == DbType.Int16) return affinity;
if (typ == DbType.Int32) return affinity;
if (typ == DbType.Int64) return affinity;
if (typ == DbType.Boolean) return affinity;
if (typ == DbType.Byte) return affinity;
if (typ == DbType.DateTime && _command.Connection._sql._datetimeFormat == SQLiteDateFormats.Ticks) return affinity;
break;
case TypeAffinity.Double:
if (typ == DbType.Single) return affinity;
if (typ == DbType.Double) return affinity;
if (typ == DbType.Decimal) return affinity;
break;
case TypeAffinity.Text:
if (typ == DbType.SByte) return affinity;
if (typ == DbType.String) return affinity;
if (typ == DbType.SByte) return affinity;
if (typ == DbType.Guid) return affinity;
if (typ == DbType.DateTime) return affinity;
break;
case TypeAffinity.Blob:
if (typ == DbType.Guid) return affinity;
if (typ == DbType.String) return affinity;
if (typ == DbType.Binary) return affinity;
break;
}
throw new InvalidCastException();
}
/// <summary>
/// Retrieves the column as a boolean value
/// </summary>
/// <param name="i">The index of the column to retrieve</param>
/// <returns>bool</returns>
public override bool GetBoolean(int i)
{
VerifyType(i, DbType.Boolean);
return Convert.ToBoolean(GetValue(i), CultureInfo.CurrentCulture);
}
/// <summary>
/// Retrieves the column as a single byte value
/// </summary>
/// <param name="i">The index of the column to retrieve</param>
/// <returns>byte</returns>
public override byte GetByte(int i)
{
VerifyType(i, DbType.Byte);
return Convert.ToByte(_activeStatement._sql.GetInt32(_activeStatement, i));
}
/// <summary>
/// Retrieves a column as an array of bytes (blob)
/// </summary>
/// <param name="i">The index of the column to retrieve</param>
/// <param name="fieldOffset">The zero-based index of where to begin reading the data</param>
/// <param name="buffer">The buffer to write the bytes into</param>
/// <param name="bufferoffset">The zero-based index of where to begin writing into the array</param>
/// <param name="length">The number of bytes to retrieve</param>
/// <returns>The actual number of bytes written into the array</returns>
/// <remarks>
/// To determine the number of bytes in the column, pass a null value for the buffer. The total length will be returned.
/// </remarks>
public override long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
{
VerifyType(i, DbType.Binary);
return _activeStatement._sql.GetBytes(_activeStatement, i, (int)fieldOffset, buffer, bufferoffset, length);
}
/// <summary>
/// Returns the column as a single character
/// </summary>
/// <param name="i">The index of the column to retrieve</param>
/// <returns>char</returns>
public override char GetChar(int i)
{
VerifyType(i, DbType.SByte);
return Convert.ToChar(_activeStatement._sql.GetInt32(_activeStatement, i));
}
/// <summary>
/// Retrieves a column as an array of chars (blob)
/// </summary>
/// <param name="i">The index of the column to retrieve</param>
/// <param name="fieldoffset">The zero-based index of where to begin reading the data</param>
/// <param name="buffer">The buffer to write the characters into</param>
/// <param name="bufferoffset">The zero-based index of where to begin writing into the array</param>
/// <param name="length">The number of bytes to retrieve</param>
/// <returns>The actual number of characters written into the array</returns>
/// <remarks>
/// To determine the number of characters in the column, pass a null value for the buffer. The total length will be returned.
/// </remarks>
public override long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
{
VerifyType(i, DbType.String);
return _activeStatement._sql.GetChars(_activeStatement, i, (int)fieldoffset, buffer, bufferoffset, length);
}
/// <summary>
/// Retrieves the name of the back-end datatype of the column
/// </summary>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -