// Copyright 2018 RED Software, LLC. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Odbc;
using System.Linq;
namespace IgniteEngine
{
///
/// Class to call stored procedures from a SQL database.
///
public class StoredProcedure : Object
{
///
/// The underlying ODBC command object.
///
private readonly OdbcCommand command;
///
/// The name of the stored procedure.
///
private readonly string name;
///
/// Parameters that will be modified when the command is executed.
///
private readonly Dictionary outputParameters;
///
/// Creates a new instance of the class.
///
/// The name of the stored procedure.
/// The connection that the procedure is being ran on.
public StoredProcedure(string name, OdbcConnection connection)
{
this.name = name;
command = connection.CreateCommand();
command.CommandType = CommandType.StoredProcedure;
outputParameters = new Dictionary();
}
///
/// Adds an output parameter to the procedure.
///
/// The type of the value.
/// The name of the parameter.
/// The data length of the value.
public void AddOutput(string name, int size = -1)
{
if (outputParameters.ContainsKey(name))
{
return;
}
var parameter = command.Parameters.AddWithValue(name, default(T));
parameter.Direction = ParameterDirection.Output;
if (typeof(T) == typeof(byte[]))
{
parameter.DbType = DbType.Binary;
parameter.OdbcType = OdbcType.Binary;
}
if (size != -1)
{
parameter.Size = size;
}
outputParameters.Add(name, default(T));
}
///
/// Adds a parameter to the procedure.
///
/// The name of the parameter.
/// The value to pass to the procedure.
/// The data length of the value.
public void AddParameter(string name, object value, int size = -1)
{
var parameter = command.Parameters.AddWithValue(name, value);
if (size != -1)
{
parameter.Size = size;
}
}
///
/// Finalizes the output variables before returning from the query.
///
public void FinalizeOutput()
{
for (var i = 0; i < outputParameters.Count; i++)
{
var output = outputParameters.ElementAt(i);
outputParameters[output.Key] = command.Parameters[output.Key].Value;
}
}
///
/// Gets a value from the output parameters.
///
/// The type of the value.
/// The name of the parameter.
public T GetOutput(string name)
{
if (!outputParameters.ContainsKey(name) || outputParameters[name] is DBNull)
{
return default(T);
}
return (T) outputParameters[name];
}
///
/// Runs the command.
///
public StoredProcedure Run()
{
SetCommandText();
command.ExecuteNonQuery();
FinalizeOutput();
return this;
}
///
/// Runs the command and returns an instance.
///
public OdbcDataReader RunReader()
{
SetCommandText();
var reader = command.ExecuteReader();
FinalizeOutput();
return reader;
}
///
/// Sets the command's text.
///
public void SetCommandText()
{
command.CommandText = $"{{call {name}";
if (command.Parameters.Count > 0)
{
command.CommandText += "(";
for (var i = 0; i < command.Parameters.Count; i++)
{
command.CommandText += "?, ";
}
command.CommandText = command.CommandText.Substring(0, command.CommandText.LastIndexOf(", ", StringComparison.Ordinal));
command.CommandText += ")";
}
command.CommandText += "}";
}
///
/// Destroys the instance.
///
protected override void Destroy()
{
command.Dispose();
}
}
}