Dies ist wahrscheinlich ein Oldie-aber-Goodie. Ich verwende System.Data.Common für eine austauschbare Oracle/SQL Server/SQLite-Datenzugriffsbibliothek. Während des Konstruktors nehme ich den Namen der Verbindungszeichenfolge und verwende diesen, um den zugrunde liegenden Providertyp zu bestimmen. Der Grund, warum ich dies tue, ist die unterschiedlichen IDbParameter-Namenskonventionen für jeden Anbieter zu behandeln. Oracle mag zum Beispiel :parameter, während SQL Server und SQLite @parameter bevorzugen. Der Standardwert ist ?, um Oledb abzudecken.
Frage: Ist das alles unnötig und gibt es eine einfache Sache, die ich übersehe, die sich einfach darum kümmern sollte? Wenn mein IDbCommand.CommandText = "select id, name from my.table where id = :id" ist, bin ich dann sicher? Im Moment nehme ich nur ? als Standard und dann RegEx'ing meinen Weg zum richtigen Parameter-Bezeichner vor der Ausführung des Befehls.
Danke.
/// <summary>
/// Initializes a new instance of the <see cref="RelationalGateway"/> class.
/// </summary>
/// <remarks>You must pass in the name of the connection string from the application configuration
/// file rather than the connection string itself so that the class can determine
/// which data provider to use, e.g., SqlClient vs. OracleClient.</remarks>
public RelationalGateway(string connectionStringName)
{
if (string.IsNullOrEmpty(connectionStringName)) throw new ArgumentNullException("connectionStringName");
if (ConfigurationManager.ConnectionStrings[connectionStringName] == null ||
ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString.Length == 0 ||
ConfigurationManager.ConnectionStrings[connectionStringName].ProviderName.Length == 0)
{
throw new InvalidOperationException(string.Format(
"The configuration file does not contain the {0} connection ",
connectionStringName) +
"string configuration section or the section contains empty values. Please ensure the " +
"configuration file has the appropriate values and try again.");
}
_connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
_providerName = ConfigurationManager.ConnectionStrings[connectionStringName].ProviderName;
_theProvider = DbProviderFactories.GetFactory(_providerName);
_adapter = _theProvider.CreateDataAdapter();
//GetConnection();
DetermineProviderSpecificParameters();
}
Das Bit DetermineProviderSpecificParameters ermittelt im Grunde genommen "?" oder ":" oder "@" oder etwas anderes.
UPDATE Hier ist, wie ich bisher mit den Details umgegangen bin:
-
Holen Sie sich den richtigen Parameterstring:
private void DetermineProviderSpecificParameters() { // Prüfung auf unterstützte Anbieter. Dies dient dazu, dass parametrisierte Abfragen zur Einschränkung // nach räumlicher Ausdehnung korrekt erstellt werden. string shortName = _providerName.Substring(_providerName.LastIndexOf(".") + 1);
switch (shortName) { case "SqlClient": _param = "@"; _ql = "["; _qr = "]"; break; case "SQLite": _param = "@"; _ql = string.Empty; _qr = string.Empty; break; case "OracleClient": _param = ":"; _ql = string.Empty; _qr = string.Empty; break; default: _param = "?"; _ql = string.Empty; _qr = string.Empty; break; } }
-
ein kleines Hilfsprogramm aufrufen, bevor ich jeden Befehl ausführe, um ihn zu "bereinigen" oder zu "parametrisieren" oder wie auch immer wir diesen halbherzigen Hack nennen:
private void MakeProviderSpecific(IDbCommand command) { foreach (IDataParameter param in command.Parameters) { param.ParameterName = GetProviderSpecificCommandText(param.ParameterName); } command.CommandText = GetProviderSpecificCommandText(command.CommandText); }
-
Und dies ruft eine kleine Regex zu tun, zu tun:
public string GetProviderSpecificCommandText(string rawCommandText) { return Regex.Replace(rawCommandText, @"\B\?\w+", new MatchEvaluator(SpecificParam)); }
Igitt. Ich suche immer noch nach einer relativ einfachen Lösung, aber die bisherigen Ratschläge sind sehr willkommen.