Passage chaîne vide / vide à la procédure stockée Oracle de asp.net
-
23-09-2019 - |
Question
Nous avons un service Web ASP.NET qui appelle une procédure stockée sur notre base de données (Oracle 11g). Le problème est que l'appel à la procédure explose à chaque fois une chaîne vide est passée comme l'un des paramètres. Nous assistons à une ORA-01084 erreur, ce qui me indique à cet appel échoue avant la procédure est exécutée en fait.
Voici la procédure, moins une certaine logique que je crois est pas pertinente:
PROCEDURE CreateReport
(
from_dt IN NVARCHAR2,
to_dt IN NVARCHAR2,
p_table_id IN NVARCHAR2,
p_column_id IN NVARCHAR2,
device_name IN NVARCHAR2,
ret_cursor OUT t_cursor
)
AS
v_cursor t_cursor;
dateStr NVARCHAR2(200);
sqlStmt VARCHAR2(10000);
extraColumns NVARCHAR2(10000);
BEGIN
/* SNIP Cut logic that builds the query statement based on inputs */
OPEN v_cursor FOR sqlStmt;
ret_cursor := v_cursor;
END CreateReport;
Voici l'invocation de CreateReport
du service Web:
public DataSet CreateReport(string fromDt, string toDate, string tableNames,
string columnNames, string deviceName)
{
DataSet dataSet;
string fmDateStr = String.IsNullOrEmpty(fromDt) ? String.Empty : fromDt.Trim();
string toDateStr = String.IsNullOrEmpty(toDate) ? String.Empty : toDate.Trim();
OracleCommand oleDBCmd = new OracleCommand();
oleDBCmd.CommandType = CommandType.StoredProcedure;
oleDBCmd.CommandText = "Web_Pkg.CreateReport";
oleDBCmd.Parameters.Add(new OracleParameter("from_dt", OracleType.NVarChar));
oleDBCmd.Parameters["from_dt"].Value = fmDateStr;
oleDBCmd.Parameters["from_dt"].Direction = ParameterDirection.Input;
oleDBCmd.Parameters.Add(new OracleParameter("to_dt", OracleType.NVarChar));
oleDBCmd.Parameters["to_dt"].Value = toDateStr;
oleDBCmd.Parameters["to_dt"].Direction = ParameterDirection.Input;
oleDBCmd.Parameters.Add(new OracleParameter("p_table_id", OracleType.NVarChar));
oleDBCmd.Parameters["p_table_id"].Value = tableNames;
oleDBCmd.Parameters["p_table_id"].Direction = ParameterDirection.Input;
oleDBCmd.Parameters.Add(new OracleParameter("p_column_id", OracleType.LongVarChar));
oleDBCmd.Parameters["p_column_id"].Value = columnNames;
oleDBCmd.Parameters["p_column_id"].Direction = ParameterDirection.Input;
oleDBCmd.Parameters.Add(new OracleParameter("device_name", OracleType.LongVarChar));
oleDBCmd.Parameters["device_name"].Value = deviceName;
oleDBCmd.Parameters["device_name"].Direction = ParameterDirection.Input;
oleDBCmd.Parameters.Add(new OracleParameter("ret_cursor", OracleType.Cursor));
oleDBCmd.Parameters["ret_cursor"].Direction = ParameterDirection.Output;
try
{
// Throws exception if any of the paramters are String.Emtpy
dataSet = DB.SQLSelect(oleDBCmd, connStr);
}
catch (Exception exp)
{
return null;
}
finally
{
if (oleDBCmd != null)
{
oleDBCmd.Dispose();
}
}
return dataSet;
}
A titre d'expérience, j'ai modifié le service Web pour passer null
plutôt que d'une chaîne vide. Lorsque null
est transmis, je vois une erreur indiquant « mauvais numéro ou les types d'arguments en appel à « CreateReport ».
J'ai aussi essayé passer DBNull.Value
chaque fois que les params étaient nuls / vides, mais qui a abouti à l'erreur
Parameter 'p_column_id': No size set for variable length data type: String.
(Bien sûr, p_column_id était le paramètre vide dans ce cas).
Alors, comment puis-je passer avec succès des chaînes vides en tant que paramètres à ma procédure stockée? Nous voulons certainement permettre au paramètre p_column_id être vide.
La solution
Vous pouvez effectuer les opérations suivantes pour tous les paramètres nullables.
oleDBCmd.Parameters.Add(new OracleParameter("to_dt", OracleType.NVarChar));
if(string.IsNullOrEmpty(toDateStr)) {
oleDBCmd.Parameters["to_dt"].Value = DBNull.Value;
} else {
oleDBCmd.Parameters["to_dt"].Value = toDateStr;
}
oleDBCmd.Parameters["to_dt"].Direction = ParameterDirection.Input;
De cette façon, vous n'êtes pas compter sur la chaîne -.> Conversion null par l'adaptateur Oracle
Edit: Si cela ne résout pas le problème, il est le plus peut-être un décalage entre les types, vérifiez NVarChar vs VarChar