Это, наверное, старенький, но гуди. Я использую System.Data.Common для сменной библиотеки доступа к данным Oracle / SQL Server / SQLite. Во время конструктора я беру имя строки подключения и использую его для определения базового типа провайдера. Причина, по которой я это делаю, состоит в том, чтобы обрабатывать разные соглашения об именах IDbParameter для каждого провайдера. Например, Oracle любит: параметр, тогда как SQL Server и SQLite любят @parameter. По умолчанию это? накрыть оледб.
Вопрос: Это все излишне и есть какая-то простая вещь, по которой я скучаю, которая должна просто позаботиться об этом? Если мой IDbCommand.CommandText = "выбрать идентификатор, имя из my.table где id =: id", я покрыт? Пока я просто усыновляю? как значение по умолчанию и затем RegEx'ing мой путь к правильному идентификатору параметра перед выполнением команды.
Спасибо.
/// <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();
}
Бит DetermineProviderSpecificParameters в основном вычисляет "?" или ":" или "@" или что-то еще.
UPDATE
Вот как я до сих пор работаю с деталями:
Получить правильную строку параметров:
private void DetermineProviderSpecificParameters ()
{
// Проверка поддерживаемых провайдеров. Это чтобы параметризованные запросы ограничивались
// по пространственному экстенту правильно созданы.
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;
}
}
вызовите маленького помощника, прежде чем я выполню каждую команду, чтобы «очистить» или «указать параметры», или как мы называем этот недоделанный хак
private void MakeProviderSpecific(IDbCommand command)
{
foreach (IDataParameter param in command.Parameters)
{
param.ParameterName = GetProviderSpecificCommandText(param.ParameterName);
}
command.CommandText = GetProviderSpecificCommandText(command.CommandText);
}
И это вызывает небольшое регулярное выражение, чтобы сделать:
public string GetProviderSpecificCommandText(string rawCommandText)
{
return Regex.Replace(rawCommandText, @"\B\?\w+", new MatchEvaluator(SpecificParam));
}
Тьфу. Все еще в поисках относительно простого решения, но совет, безусловно, ценится.