Skip to content

Instantly share code, notes, and snippets.

@dibley1973
Last active December 3, 2015 20:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dibley1973/bf4391ee08554e46dcd3 to your computer and use it in GitHub Desktop.
Save dibley1973/bf4391ee08554e46dcd3 to your computer and use it in GitHub Desktop.
C# DbCommand Creator for use with Stored Procedures that is set up with a fluid API
using Dibware.StoredProcedureFramework.Helpers.Base;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
namespace Dibware.StoredProcedureFramework.Helpers
{
public class StoredProcedureDbCommandCreator
: DbCommandCreatorBase
{
#region Constructor
private StoredProcedureDbCommandCreator(DbConnection connection)
: base(connection)
{}
#endregion
#region Public Members
/// <summary>
/// Builds and sets up the command based upon the settings that have
/// been previously passed to this builder.
/// </summary>
/// <remarks>
/// Should call into base implementation before executing any addtional code
/// </remarks>
public new void BuildCommand()
{
base.BuildCommand();
}
#endregion
#region Public Factory Methods
/// <summary>
/// Creates the stored procedure database command creator.
/// </summary>
/// <param name="connection">
/// The connection to be passed to the command when it is constructed.
/// </param>
/// <param name="procedureName">
/// The name of the stored procedure for which the commmand is to call.
/// </param>
/// <returns></returns>
/// <exception cref="System.ArgumentNullException">
/// connection
/// or
/// procedureName
/// </exception>
public static StoredProcedureDbCommandCreator CreateStoredProcedureDbCommandCreator(
DbConnection connection,
string procedureName)
{
if (connection == null) throw new ArgumentNullException("connection");
if (string.IsNullOrWhiteSpace(procedureName)) throw new ArgumentNullException("procedureName");
var builder = new StoredProcedureDbCommandCreator(connection)
.WithCommandText(procedureName)
.WithCommandType(CommandType.StoredProcedure);
return builder;
}
/// <summary>
/// Adds a command timeout to the builder which will be passed to the command
/// when it is construted.
/// </summary>
/// <param name="commandTimeout">The value of the command timeout.</param>
/// <returns></returns>
public new StoredProcedureDbCommandCreator WithCommandTimeout(int commandTimeout)
{
base.WithCommandTimeout(commandTimeout);
return this;
}
/// <summary>
/// Adds the specified parameters to the builder, and these will be added
/// to the command when it is built.
/// </summary>
/// <param name="parameters">The parameters to add to the command.</param>
/// <returns></returns>
public new StoredProcedureDbCommandCreator WithParameters(IEnumerable<SqlParameter> parameters)
{
base.WithParameters(parameters);
return this;
}
/// <summary>
/// Adds the specified transaction to the builder, and these will be added
/// to the command when it is built.
/// </summary>
/// <param name="transaction">The transaction to add to teh command.</param>
/// <returns></returns>
public new StoredProcedureDbCommandCreator WithTransaction(SqlTransaction transaction)
{
base.WithTransaction(transaction);
return this;
}
#endregion
#region Private Members
private new StoredProcedureDbCommandCreator WithCommandText(string commandText)
{
base.WithCommandText(commandText);
return this;
}
private new StoredProcedureDbCommandCreator WithCommandType(CommandType commandType)
{
base.WithCommandType(commandType);
return this;
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
namespace Dibware.StoredProcedureFramework.Helpers.Base
{
public abstract class DbCommandCreatorBase
{
#region Fields
private DbCommand _command;
private readonly DbConnection _connection;
private IEnumerable<SqlParameter> _parameters;
private string _commandText;
private int? _commandTimeout;
private SqlTransaction _transaction;
private CommandType _commandType;
#endregion
#region Constructor
/// <summary>
/// Initializes a new instance of the <see cref="DbCommandCreatorBase"/> class.
/// </summary>
/// <param name="connection">
/// The DbConnection to run the command against.
/// </param>
/// <exception cref="System.ArgumentNullException">connection</exception>
protected DbCommandCreatorBase(DbConnection connection)
{
if (connection == null) throw new ArgumentNullException("connection");
_connection = connection;
}
#endregion
#region Public Members
/// <summary>
/// Builds and sets up the command based upon the settings that have
/// been previously passed to this builder.
/// </summary>
protected void BuildCommand()
{
CreateCommand();
LoadCommandParametersIfAnyExist();
SetCommandText();
SetCommandType();
SetCommandTimeoutIfExists();
SetTransactionIfExists();
}
/// <summary>
/// Gets the command or null if it has not been built.
/// </summary>
/// <value>
/// The command.
/// </value>
public DbCommand Command
{
get { return _command; }
}
#endregion
#region Private and Protected Members
private void AddParametersToCommand()
{
foreach (SqlParameter parameter in _parameters)
{
_command.Parameters.Add(parameter);
}
}
private void ClearAnyExistingParameters()
{
bool parametersRequireClearing = (_command.Parameters.Count > 0);
if (parametersRequireClearing)
{
_command.Parameters.Clear();
}
}
private void CreateCommand()
{
_command = _connection.CreateCommand();
}
private bool HasParameters
{
get { return _parameters != null; }
}
protected void LoadCommandParametersIfAnyExist()
{
if (HasParameters)
{
ClearAnyExistingParameters();
AddParametersToCommand();
}
}
private void SetCommandText()
{
_command.CommandText = _commandText;
}
private void SetCommandType()
{
_command.CommandType = _commandType;
}
private void SetCommandTimeoutIfExists()
{
bool hasCommandTimeout = _commandTimeout.HasValue;
if (hasCommandTimeout)
{
_command.CommandTimeout = _commandTimeout.Value;
}
}
private void SetTransactionIfExists()
{
bool hasTransaction = _transaction != null;
if (hasTransaction) _command.Transaction = _transaction;
}
protected void WithCommandText(string commandText)
{
_commandText = commandText;
}
protected void WithCommandTimeout(int commandTimeout)
{
_commandTimeout = commandTimeout;
}
protected void WithCommandType(CommandType commandType)
{
_commandType = commandType;
}
protected void WithParameters(IEnumerable<SqlParameter> parameters)
{
_parameters = parameters;
}
protected void WithTransaction(SqlTransaction transaction)
{
_transaction = transaction;
}
#endregion
}
}
using Dibware.StoredProcedureFramework.Helpers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
namespace Dibware.StoredProcedureFramework.Tests.UnitTests.Helpers
{
[TestClass]
public class StoredProcedureDbCommandCreatorTests
{
#region Fields
const string StoredProcedureName = "DummyProcedure";
const string ConnectionString = "Server=myServerAddress;Database=myDataBase;Trusted_Connection=True;";
SqlConnection _connection;
#endregion
#region Properties
private SqlConnection Connection
{
get { return _connection; }
}
#endregion
#region Test Pre and Clear down
[TestInitialize]
public void TestSetup()
{
_connection = new SqlConnection(ConnectionString);
}
[TestCleanup]
public void TestCleanup()
{
if (_connection != null)
{
if (_connection.State != ConnectionState.Closed)
{
_connection.Close();
}
_connection.Dispose();
}
}
#endregion
#region Tests
#region Command
[TestMethod]
public void CommandProperty_WhenBuildCommmandNotCalled_ReturnsNull()
{
// ARRANGE
var builder = StoredProcedureDbCommandCreator.CreateStoredProcedureDbCommandCreator(Connection, StoredProcedureName);
// ACT
var actualCommand = builder.Command;
// ASSERT
Assert.IsNull(actualCommand);
}
[TestMethod]
public void CommandProperty_WhenBuildCommmandIsCalled_ReturnsInstance()
{
// ARRANGE
var builder = StoredProcedureDbCommandCreator.CreateStoredProcedureDbCommandCreator(Connection, StoredProcedureName);
// ACT
builder.BuildCommand();
var actualCommand = builder.Command;
// ASSERT
Assert.IsNotNull(actualCommand);
}
[TestMethod]
public void CommandProperty_WhenBuildCommmandTwice_ReturnsDistinctInstances()
{
// ARRANGE
var builder = StoredProcedureDbCommandCreator.CreateStoredProcedureDbCommandCreator(Connection, StoredProcedureName);
// ACT
builder.BuildCommand();
var actualCommand1 = builder.Command;
builder.BuildCommand();
var actualCommand2 = builder.Command;
// ASSERT
Assert.AreNotSame(actualCommand1, actualCommand2);
}
#endregion
#region CommandText
[TestMethod]
public void CommandText_WhenBuildCommmandIsCalled_ReturnsProcedureName()
{
// ARRANGE
var builder = StoredProcedureDbCommandCreator.CreateStoredProcedureDbCommandCreator(Connection, StoredProcedureName);
// ACT
builder.BuildCommand();
var actualCommand = builder.Command;
var actualCommandText = actualCommand.CommandText;
// ASSERT
Assert.AreEqual(StoredProcedureName, actualCommandText);
}
#endregion
#region CommandTimeout
[TestMethod]
public void CommandTimout_WhenWithCommandTimeoutNotCalled_ReturnsDefaultTimeout()
{
// ARRANGE
const int defaultCommandTimeout = 30;
var builder = StoredProcedureDbCommandCreator.CreateStoredProcedureDbCommandCreator(Connection, StoredProcedureName);
// ACT
builder.BuildCommand();
var actualCommand = builder.Command;
var actualCommandTimeout = actualCommand.CommandTimeout;
// ASSERT
Assert.AreEqual(defaultCommandTimeout, actualCommandTimeout);
}
[TestMethod]
public void CommandTimout_WhenWithCommandTimeoutIsCalled_ReturnsCorrectTimeout()
{
// ARRANGE
const int expectedCommandTimeout = 120;
var builder = StoredProcedureDbCommandCreator.CreateStoredProcedureDbCommandCreator(Connection, StoredProcedureName);
// ACT
builder
.WithCommandTimeout(expectedCommandTimeout)
.BuildCommand();
var actualCommand = builder.Command;
var actualCommandText = actualCommand.CommandTimeout;
// ASSERT
Assert.AreEqual(expectedCommandTimeout, actualCommandText);
}
#endregion
#region CommandType
[TestMethod]
public void CommandType_WhenBuildCommmandIsCalled_ReturnsStoredProcedureCommandType()
{
// ARRANGE
const CommandType expectedCommandType = CommandType.StoredProcedure;
var builder = StoredProcedureDbCommandCreator.CreateStoredProcedureDbCommandCreator(Connection, StoredProcedureName);
// ACT
builder.BuildCommand();
var actualCommand = builder.Command;
var actualCommandType = actualCommand.CommandType;
// ASSERT
Assert.AreEqual(expectedCommandType, actualCommandType);
}
#endregion
#region Parameters
[TestMethod]
public void Parameters_WhenBuildCommmandIsNotCalled_ReturnsEmptParameterCollection()
{
// ARRANGE
var builder = StoredProcedureDbCommandCreator.CreateStoredProcedureDbCommandCreator(Connection, StoredProcedureName);
// ACT
builder.BuildCommand();
var actualCommand = builder.Command;
var actualParameters = actualCommand.Parameters;
// ASSERT
Assert.AreEqual(0, actualParameters.Count);
}
[TestMethod]
public void Parameters_WhenBuildCommmandIsCalledAndParametersWasSupplied_ReturnsSameInstance()
{
// ARRANGE
var expectedParameters = new List<SqlParameter>
{
new SqlParameter("Id", SqlDbType.Int),
new SqlParameter("Name", SqlDbType.NVarChar),
};
var builder = StoredProcedureDbCommandCreator.CreateStoredProcedureDbCommandCreator(Connection, StoredProcedureName);
// ACT
builder
.WithParameters(expectedParameters)
.BuildCommand();
var actualCommand = builder.Command;
var actualParameters = actualCommand.Parameters;
// ASSERT
Assert.AreSame(expectedParameters[0], actualParameters[0]);
Assert.AreSame(expectedParameters[1], actualParameters[1]);
}
#endregion
#region Transaction
[TestMethod]
[Ignore] // Requires a valid connection first!
public void Transaction_WhenBuildCommmandIsNotCalled_ReturnsNull()
{
// ARRANGE
SqlTransaction expectedTransaction = Connection.BeginTransaction();
var builder = StoredProcedureDbCommandCreator.CreateStoredProcedureDbCommandCreator(Connection, StoredProcedureName);
// ACT
var actualCommand = builder.Command;
var actualCommandTransaction = actualCommand.Transaction;
// ASSERT
Assert.IsNull(actualCommandTransaction);
}
[TestMethod]
[Ignore] // Requires a valid connection first!
public void Transaction_WhenBuildCommmandIsCalled_ContainsSameInstanceAsSupplied()
{
// ARRANGE
SqlTransaction expectedTransaction = Connection.BeginTransaction();
var builder = StoredProcedureDbCommandCreator.CreateStoredProcedureDbCommandCreator(Connection, StoredProcedureName);
// ACT
builder.BuildCommand();
var actualCommand = builder.Command;
var actualCommandTransaction = actualCommand.Transaction;
// ASSERT
Assert.AreSame(expectedTransaction, actualCommandTransaction);
}
#endregion
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment