CodeKeep C# Feed Novembre 30th, 2007
Description: Utility class for calling DBMS_DESCRIBE.DESCRIBE_PROCEDURE to get information about the arguments of an Oracle stored procedure.
Link:
http://www.codekeep.net/snippets/7be0a2b8-4e0e-4262-a058-d77f89636150.aspx
public static class Utility
{
private static Dictionary<string, ArgumentDescription[]> procedureArguments = new Dictionary<string, ArgumentDescription[]>();
private static System.Data.DataTable allArgumentsCache = null;
/// <summary>
/// Contains the field values returned by the Oracle system procedure DBMS_DESCRIBE.DESCRIBE_PROCEDURE.
/// </summary>
public class ArgumentDescription
{
public int Overload;
public int Position;
public int Level;
public string ArgumentName;
public int DataType;
public int DefaultValue;
public int InOut;
public int Length;
public int Precision;
public int Scale;
public int Radix;
public int Spare;
}
/// <summary>
/// Calls the Oracle system procedure DBMS_DESCRIBE.DESCRIBE_PROCEDURE to return an argument of a stored procedure.
/// </summary>
/// <param name="ownerName">The package owner.</param>
/// <param name="packageName">The package containing the procedure.</param>
/// <param name="procedureName">The stored procedure name.</param>
/// <param name="argumentName">The argument name.</param>
/// <param name="connection">An <see cref="OracleConnection"/> to the Oracle database.</param>
/// <returns>An <see cref="ArgumentDescription"/> representing the argument requested, or null of no matching argument is found.</returns>
public static ArgumentDescription GetProcedureArgument(string ownerName, string packageName, string procedureName, string argumentName, OracleConnection connection)
{
argumentName = argumentName.Trim().ToUpper();
foreach (ArgumentDescription argument in GetProcedureArguments(ownerName, packageName, procedureName, connection))
{
if (argument.ArgumentName.ToUpper() == argumentName)
return argument;
}
return null;
}
/// <summary>
/// Calls the Oracle system procedure DBMS_DESCRIBE.DESCRIBE_PROCEDURE to return the arguments of a stored procedure.
/// </summary>
/// <param name="ownerName">The package owner.</param>
/// <param name="packageName">The package containing the procedure.</param>
/// <param name="procedureName">The stored procedure name.</param>
/// <param name="connection">An <see cref="OracleConnection"/> to the Oracle database.</param>
/// <returns>An array of <see cref="ArgumentDescription"/>.</returns>
public static ArgumentDescription[] GetProcedureArguments(string ownerName, string packageName, string procedureName, OracleConnection connection)
{
ownerName = ownerName.Trim().ToUpper();
packageName = packageName.Trim().ToUpper();
procedureName = procedureName.Trim().ToUpper();
string objectName = procedureName;
if (!string.IsNullOrEmpty(packageName))
objectName = packageName + "." + procedureName;
OracleCommand cmd = null;
string sql = null;
// query ALL_ARGUMENTS table once and cache list of all arguments
if (allArgumentsCache == null)
{
allArgumentsCache = new System.Data.DataTable();
sql = "select owner, package_name, object_name, argument_name, position from sys.all_arguments WHERE owner='" + ownerName + "' ";
cmd = new OracleCommand(sql, connection);
OracleDataAdapter da = new OracleDataAdapter(cmd);
da.Fill(allArgumentsCache);
}
// determine number of arguments in procedure
sql = "owner='" + ownerName + "' and object_name='" + procedureName + "' ";
if (!string.IsNullOrEmpty(packageName))
sql += " and package_name='" + packageName + "' ";
int argumentCount = Convert.ToInt32(allArgumentsCache.Compute("count(argument_name)", sql));
int argumentCountPlusOne = argumentCount + 1; // in case procedure is actually a function that returns a value
if (!procedureArguments.ContainsKey(objectName))
{
cmd = new OracleCommand("DBMS_DESCRIBE.DESCRIBE_PROCEDURE", connection);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("OBJECT_NAME", OracleDbType.Varchar2).Value = objectName;
cmd.Parameters.Add("RESERVED1", "");
cmd.Parameters.Add("RESERVED2", "");
int bindSize = 30;
int[] arrayBindSize = new int[argumentCountPlusOne];
for (int i = 0; i < argumentCountPlusOne; i++)
arrayBindSize[i] = bindSize;
// setup the OUT associative arrays
string[] paramnames = new string[12] { "OVERLOAD", "POSITION", "LEVEL", "ARGUMENT_NAME", "DATATYPE", "DEFAULT_VALUE", "IN_OUT", "LENGTH", "PRECISION", "SCALE", "RADIX", "SPARE" };
for (int i = 0; i < paramnames.Length; i++)
{
OracleParameter p = null;
if (paramnames[i] != "ARGUMENT_NAME")
p = new OracleParameter(paramnames[i], OracleDbType.Int32, argumentCountPlusOne, null, System.Data.ParameterDirection.Output);
else
{
// need to set sizes on varchar2 params
p = new OracleParameter("ARGUMENT_NAME", OracleDbType.Varchar2, argumentCountPlusOne, null, System.Data.ParameterDirection.Output);
p.ArrayBindSize = arrayBindSize;
}
p.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
cmd.Parameters.Add(p);
}
cmd.ExecuteNonQuery();
argumentCount = (cmd.Parameters[3].Value as Array).Length;
ArgumentDescription[] argument = new ArgumentDescription[argumentCount];
for (int i = 0; i < argumentCount; i++)
{
int j = 3;
argument[i] = new ArgumentDescription();
argument[i].Overload = Convert.ToInt32((cmd.Parameters[j++].Value as Array).GetValue(i));
argument[i].Position = Convert.ToInt32((cmd.Parameters[j++].Value as Array).GetValue(i));
argument[i].Level = Convert.ToInt32((cmd.Parameters[j++].Value as Array).GetValue(i));
argument[i].ArgumentName = Convert.ToString((cmd.Parameters[j++].Value as Array).GetValue(i));
argument[i].DataType = Convert.ToInt32((cmd.Parameters[j++].Value as Array).GetValue(i));
argument[i].DefaultValue = Convert.ToInt32((cmd.Parameters[j++].Value as Array).GetValue(i));
argument[i].InOut = Convert.ToInt32((cmd.Parameters[j++].Value as Array).GetValue(i));
argument[i].Length = Convert.ToInt32((cmd.Parameters[j++].Value as Array).GetValue(i));
argument[i].Precision = Convert.ToInt32((cmd.Parameters[j++].Value as Array).GetValue(i));
argument[i].Scale = Convert.ToInt32((cmd.Parameters[j++].Value as Array).GetValue(i));
argument[i].Radix = Convert.ToInt32((cmd.Parameters[j++].Value as Array).GetValue(i));
argument[i].Spare = Convert.ToInt32((cmd.Parameters[j++].Value as Array).GetValue(i));
}
procedureArguments.Add(objectName, argument);
}
return procedureArguments[objectName];
}
}