Initial commit of first working version that is used in production environment.
This commit is contained in:
205
DynamORM/DynamicCommand.cs
Normal file
205
DynamORM/DynamicCommand.cs
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* DynamORM - Dynamic Object-Relational Mapping library.
|
||||
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Data;
|
||||
|
||||
namespace DynamORM
|
||||
{
|
||||
/// <summary>Helper class to easy manage command.</summary>
|
||||
public class DynamicCommand : IDbCommand
|
||||
{
|
||||
private IDbCommand _command;
|
||||
private int? _commandTimeout = null;
|
||||
private DynamicConnection _con;
|
||||
private DynamicDatabase _db;
|
||||
private long _poolStamp = 0;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="DynamicCommand"/> class.</summary>
|
||||
/// <param name="con">The connection.</param>
|
||||
/// <param name="db">The databas manager.</param>
|
||||
internal DynamicCommand(DynamicConnection con, DynamicDatabase db)
|
||||
{
|
||||
_con = con;
|
||||
_db = db;
|
||||
|
||||
lock (_db.SyncLock)
|
||||
{
|
||||
if (!_db.CommandsPool.ContainsKey(_con.Connection))
|
||||
throw new InvalidOperationException("Can't create transaction using disposed connection.");
|
||||
else
|
||||
{
|
||||
_command = _con.Connection.CreateCommand();
|
||||
_db.CommandsPool[_con.Connection].Add(_command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Prepare command for execution.</summary>
|
||||
/// <returns>Returns edited <see cref="System.Data.IDbCommand"/> instance.</returns>
|
||||
private IDbCommand PrepareForExecution()
|
||||
{
|
||||
if (_poolStamp < _db.PoolStamp)
|
||||
{
|
||||
_command.CommandTimeout = _commandTimeout ?? _db.CommandTimeout ?? _command.CommandTimeout;
|
||||
|
||||
if (_db.TransactionPool[_command.Connection].Count > 0)
|
||||
_command.Transaction = _db.TransactionPool[_command.Connection].Peek();
|
||||
|
||||
_poolStamp = _db.PoolStamp;
|
||||
}
|
||||
|
||||
return _db.DumpCommands ? _command.Dump(Console.Out) : _command;
|
||||
}
|
||||
|
||||
#region IDbCommand Members
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to cancels the execution of an <see cref="T:System.Data.IDbCommand"/>.
|
||||
/// </summary>
|
||||
public void Cancel()
|
||||
{
|
||||
_command.Cancel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text command to run against the data source.
|
||||
/// </summary>
|
||||
/// <returns>The text command to execute. The default value is an empty string ("").</returns>
|
||||
public string CommandText { get { return _command.CommandText; } set { _command.CommandText = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the wait time before terminating the attempt to execute a command and generating an error.
|
||||
/// </summary>
|
||||
/// <returns>The time (in seconds) to wait for the command to execute. The default value is 30 seconds.</returns>
|
||||
/// <exception cref="T:System.ArgumentException">The property value assigned is less than 0. </exception>
|
||||
public int CommandTimeout { get { return _commandTimeout ?? _command.CommandTimeout; } set { _commandTimeout = value; } }
|
||||
|
||||
/// <summary>Gets or sets how the <see cref="P:System.Data.IDbCommand.CommandText"/> property is interpreted.</summary>
|
||||
public CommandType CommandType { get { return _command.CommandType; } set { _command.CommandType = value; } }
|
||||
|
||||
/// <summary>Gets or sets the <see cref="T:System.Data.IDbConnection"/>
|
||||
/// used by this instance of the <see cref="T:System.Data.IDbCommand"/>.</summary>
|
||||
/// <returns>The connection to the data source.</returns>
|
||||
public IDbConnection Connection { get { return _con; } set { _con = (DynamicConnection)value; } }
|
||||
|
||||
/// <summary>Creates a new instance of an
|
||||
/// <see cref="T:System.Data.IDbDataParameter"/> object.</summary>
|
||||
/// <returns>An <see cref="IDbDataParameter"/> object.</returns>
|
||||
public IDbDataParameter CreateParameter()
|
||||
{
|
||||
return _command.CreateParameter();
|
||||
}
|
||||
|
||||
/// <summary>Executes an SQL statement against the Connection object of a
|
||||
/// data provider, and returns the number of rows affected.</summary>
|
||||
/// <returns>The number of rows affected.</returns>
|
||||
public int ExecuteNonQuery()
|
||||
{
|
||||
return PrepareForExecution().ExecuteNonQuery();
|
||||
}
|
||||
|
||||
/// <summary>Executes the <see cref="P:System.Data.IDbCommand.CommandText"/>
|
||||
/// against the <see cref="P:System.Data.IDbCommand.Connection"/>,
|
||||
/// and builds an <see cref="T:System.Data.IDataReader"/> using one
|
||||
/// of the <see cref="T:System.Data.CommandBehavior"/> values.
|
||||
/// </summary><param name="behavior">One of the
|
||||
/// <see cref="T:System.Data.CommandBehavior"/> values.</param>
|
||||
/// <returns>An <see cref="T:System.Data.IDataReader"/> object.</returns>
|
||||
public IDataReader ExecuteReader(CommandBehavior behavior)
|
||||
{
|
||||
return PrepareForExecution().ExecuteReader(behavior);
|
||||
}
|
||||
|
||||
/// <summary>Executes the <see cref="P:System.Data.IDbCommand.CommandText"/>
|
||||
/// against the <see cref="P:System.Data.IDbCommand.Connection"/> and
|
||||
/// builds an <see cref="T:System.Data.IDataReader"/>.</summary>
|
||||
/// <returns>An <see cref="T:System.Data.IDataReader"/> object.</returns>
|
||||
public IDataReader ExecuteReader()
|
||||
{
|
||||
return PrepareForExecution().ExecuteReader();
|
||||
}
|
||||
|
||||
/// <summary>Executes the query, and returns the first column of the
|
||||
/// first row in the resultset returned by the query. Extra columns or
|
||||
/// rows are ignored.</summary>
|
||||
/// <returns>The first column of the first row in the resultset.</returns>
|
||||
public object ExecuteScalar()
|
||||
{
|
||||
return PrepareForExecution().ExecuteScalar();
|
||||
}
|
||||
|
||||
/// <summary>Gets the <see cref="T:System.Data.IDataParameterCollection"/>.</summary>
|
||||
public IDataParameterCollection Parameters
|
||||
{
|
||||
get { return _command.Parameters; }
|
||||
}
|
||||
|
||||
/// <summary>Creates a prepared (or compiled) version of the command on the data source.</summary>
|
||||
public void Prepare()
|
||||
{
|
||||
_command.Prepare();
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the transaction within which the Command
|
||||
/// object of a data provider executes.</summary>
|
||||
/// <remarks>It's does nothing, transaction is peeked from transaction
|
||||
/// pool of a connection.</remarks>
|
||||
public IDbTransaction Transaction { get { return null; } set { } }
|
||||
|
||||
/// <summary>Gets or sets how command results are applied to the <see cref="T:System.Data.DataRow"/>
|
||||
/// when used by the <see cref="M:System.Data.IDataAdapter.Update(System.Data.DataSet)"/>
|
||||
/// method of a <see cref="T:System.Data.Common.DbDataAdapter"/>.</summary>
|
||||
/// <returns>One of the <see cref="T:System.Data.UpdateRowSource"/> values. The default is
|
||||
/// Both unless the command is automatically generated. Then the default is None.</returns>
|
||||
/// <exception cref="T:System.ArgumentException">The value entered was not one of the
|
||||
/// <see cref="T:System.Data.UpdateRowSource"/> values. </exception>
|
||||
public UpdateRowSource UpdatedRowSource { get { return _command.UpdatedRowSource; } set { _command.UpdatedRowSource = value; } }
|
||||
|
||||
#endregion IDbCommand Members
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
/// <summary>Performs application-defined tasks associated with
|
||||
/// freeing, releasing, or resetting unmanaged resources.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
lock (_db.SyncLock)
|
||||
{
|
||||
var pool = _db.CommandsPool.TryGetValue(_con.Connection);
|
||||
|
||||
if (pool != null)
|
||||
pool.Remove(_command);
|
||||
|
||||
_command.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion IDisposable Members
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user