// 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(); } } }