2010-03-01 2 views
1

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 qu'une chaîne vide est passée comme l'un des paramètres. Une erreur ORA-01084 apparaît, ce qui indique que l'appel échoue avant l'exécution de la procédure.Passage de la chaîne vide/vide à la procédure stockée Oracle d'asp.net

est ici 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 web service pour passer null plutôt que des chaînes vides. Lorsque null est transmise, je vois une erreur indiquant "nombre incorrect ou types d'arguments dans l'appel à 'CREATEREPORT."

J'ai aussi essayé passer DBNull.Value chaque fois que les params étaient nuls/vides, mais qui a donné lieu à 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 absolument permettre au paramètre p_column_id d'être vide.

Répondre

3

Vous pouvez effectuer les opérations suivantes pour tous les paramètres Nullable.

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 ne comptez pas sur la conversion chaîne -> 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

+0

Il était en effet une incompatibilité de type. Les paramètres device_name et p_column_id utilisent le type incorrect dans le service Web. Ils sont OracleType.LongVarChar, mais ils devraient être OracleType.NVarChar. Merci! – Odrade

Questions connexes