2010-03-09 19 views
9

ich eine SQL-Anweisung, die ich durch OleDb bin ausführt, ist die Aussage etwas wie folgt aus:OleDbParameters und Parameternamen

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

Ich füge Parameter an die OleDbCommand wie folgt aus:

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); 

Das Problem, das ich habe, ist, wenn ich die Parameter hinzufügen, anders herum, dann die Spalten mit den falschen Werten (dh Name ist in der Abteilung Spalte und umgekehrt)

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

Meine Frage ist, was ist der Sinn der Parameternamen, wenn Parameterwerte nur in der Reihenfolge in die Tabelle eingefügt werden, in der sie Befehl hinzugefügt werden? Die Parameternamen scheinen redundant zu sein.

Jede Hilfe apprreciated, Danke, Gareth

Antwort

4

Parameternamen sind generisch in dem SQL-Support-System (das heißt nicht OleDb spezifisch). Ziemlich viel NUR OleDb/Odbc benutzen sie NICHT. Sie sind da, weil OleDb eine spezifische Implementierung der generischen Basisklassen ist.

+0

Das etwas ärgerlich ist, na ja, den Code ändern, müssen Sie die Werte in der richtigen hinzufügen bestellen, Danke – Gaz

+0

es ist verdammt nervig. Ernst. Und wenn Sie jemals ODBC ausprobieren, denke ich, Sie sind für "?" als param name oder so ähnlich (vor langer Zeit);) – TomTom

+0

Seltsam, weil 'DbParameter' kein ParameterName-Feld hat - Sie würden denken, wenn 'OleDbParameter' den ParameterName nicht verwendet, würden sie ihn nicht der Klasse hinzufügen .. –

11

Das Problem ist, dass OleDb (und Odbc auch) benannte Parameter nicht unterstützt.
Es unterstützt nur so genannte Positionsparameter.

Mit anderen Worten: Der Name, den Sie einen Parameter geben, wenn Sie es der Befehlsparameterliste hinzufügen, spielt keine Rolle. Es wird nur intern von der OleDbCommand-Klasse verwendet, so dass die Parameter unterschieden und referenziert werden können.

Wichtig ist die Reihenfolge, in der Sie die Parameter zur Liste hinzufügen. Es muss dieselbe Reihenfolge sein, in der die Parameter in der SQL-Anweisung über das Fragezeichen (?) Referenziert werden.

Aber hier ist eine Lösung, mit der Sie benannte Parameter in der SQL-Anweisung verwenden können.
Es ersetzt grundsätzlich alle Parameterreferenzen in der SQL-Anweisung durch Fragezeichen und ordnet die Parameterliste entsprechend um. Es funktioniert auf die gleiche Weise für die OdbcCommand-Klasse, Sie müssen nur "OleDb" durch "Odbc" im Code ersetzen.

den Code wie folgt verwenden:

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

Und hier ist der Code

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