2010-03-09 14 views
9

ho un'istruzione SQL che sto eseguendo attraverso OleDb, l'istruzione è qualcosa di simile:OleDbParameters e il parametro nomi

INSERT INTO mytable (name, dept) VALUES (@name, @dept); 

sto aggiungendo parametri alla OleDbCommand in questo modo:

OleDbCommand Command = new OleDbCommand(); 
Command.Connection = Connection; 

OleDbParameter Parameter1 = new OleDbParameter(); 
Parameter1.OleDbType = OleDbType.VarChar; 
Parameter1.ParamterName = "@name"; 
Parameter1.Value = "Bob"; 

OleDbParameter Parameter2 = new OleDbParameter(); 
Parameter2.OleDbType = OleDbType.VarChar; 
Parameter2.ParamterName = "@dept"; 
Parameter2.Value = "ADept"; 

Command.Parameters.Add(Parameter1); 
Command.Parameters.Add(Parameter2); 

Il problema che ho è, se aggiungo i parametri al comando viceversa, le colonne vengono popolate con valori errati (ad esempio il nome è nella colonna dept e viceversa)

Command.Parameters.Add(Parameter2); 
Command.Parameters.Add(Parameter1); 

La mia domanda è, qual è il punto dei nomi dei parametri se i valori dei parametri sono appena inseriti nella tabella nell'ordine in cui sono aggiunti i comandi? I nomi dei parametri sembrano ridondanti?

Qualsiasi aiuto apprreciated, Grazie, Gareth

risposta

4

nomi dei parametri sono generico sistema di supporto SQL (cioè non OleDb specifico). Praticamente solo OleDb/Odbc NON li usa. Sono lì perché OleDb è un'implementazione specifica delle classi base generiche.

+0

Questo è un po 'fastidioso, vabbè, dovrà modificare il codice per aggiungere i valori nella corretta Per favore, grazie – Gaz

+0

è terribilmente fastidioso. Sul serio. E se mai provi ODBC, penso, sei pronto per "?" come nome param o qualcosa del genere (molto tempo fa);) – TomTom

+0

Strano, perché 'DbParameter' NON ha un campo ParameterName - penseresti che se' OleDbParameter' non usa il ParameterName, non lo aggiungerebbero alla classe .. –

11

Il problema è che OleDb (e anche Odbc) non supporta i parametri denominati.
Supporta solo i cosiddetti parametri posizionali.

In altre parole: il nome assegnato a un parametro quando viene aggiunto all'elenco dei parametri dei comandi non ha importanza. Viene utilizzato solo internamente dalla classe OleDbCommand in modo che possa distinguere e fare riferimento ai parametri.

Ciò che importa è l'ordine in cui si aggiungono i parametri all'elenco. Deve essere lo stesso ordine in cui i parametri sono referenziati nell'istruzione SQL tramite il carattere del punto interrogativo (?).

Ma ecco una soluzione che consente di utilizzare parametri denominati nell'istruzione SQL.
Sostituisce sostanzialmente tutti i riferimenti dei parametri nell'istruzione SQL con punti interrogativi e riordina di conseguenza l'elenco dei parametri. Funziona allo stesso modo per la classe OdbcCommand, è sufficiente sostituire "OleDb" con "Odbc" nel codice.

utilizzare il codice in questo modo:

command.CommandText = "SELECT * FROM Contact WHERE FirstName = @FirstName"; 
command.Parameters.AddWithValue("@FirstName", "Mike"); 
command.ConvertNamedParametersToPositionalParameters(); 

Ed ecco il codice

public static class OleDbCommandExtensions 
{ 
    public static void ConvertNamedParametersToPositionalParameters(this OleDbCommand command) 
    { 
     //1. Find all occurrences of parameter references in the SQL statement (such as @MyParameter). 
     //2. Find the corresponding parameter in the commands parameters list. 
     //3. Add the found parameter to the newParameters list and replace the parameter reference in the SQL with a question mark (?). 
     //4. Replace the commands parameters list with the newParameters list. 

     var newParameters = new List<OleDbParameter>(); 

     command.CommandText = Regex.Replace(command.CommandText, "(@\\w*)", match => 
     { 
      var parameter = command.Parameters.OfType<OleDbParameter>().FirstOrDefault(a => a.ParameterName == match.Groups[1].Value); 
      if (parameter != null) 
      { 
       var parameterIndex = newParameters.Count; 

       var newParameter = command.CreateParameter(); 
       newParameter.OleDbType = parameter.OleDbType; 
       newParameter.ParameterName = "@parameter" + parameterIndex.ToString(); 
       newParameter.Value = parameter.Value; 

       newParameters.Add(newParameter); 
      } 

      return "?"; 
     }); 

     command.Parameters.Clear(); 
     command.Parameters.AddRange(newParameters.ToArray()); 
    } 
}