Связывание параметров запроса по имени с ODP.NET

В настоящее время я использую поставщик Microsoft ADO.NET для Oracle (System.Data.OracleClient). Я знаю, что это, безусловно, не лучший поставщик Oracle, и что он скоро будет устаревшим, вместо этого я должен использовать Oracle ODP.NET, Причина, по которой я все еще использую поставщика MS, заключается в том, что ODP.NET привязывает параметры по позиции, а не по имени. Это действительно может быть PITA, когда вы используете много параметров в запросе, потому что вы должны быть осторожны, чтобы добавить их в правильном порядке, что может легко привести к ошибкам. Это также раздражает, когда вы используете один и тот же параметр несколько раз в одном запросе, например:

SELECT A,B,C FROM FOO WHERE X = :PARAM_X OR :PARAM_X = 0

С ODP.NET я должен добавить два параметра в OracleCommand, который, я думаю, глуп...

ODP.NET OracleCommand имеет свойство изменять это поведение по умолчанию: BindByName. Когда установлено значение true, параметры связаны по имени, и это то, что я хочу. К сожалению, это мне не очень помогает, потому что:

  • По умолчанию установлено значение false
  • Я почти никогда не использую конкретные классы ADO.NET явно, я предпочитаю использовать уровень абстракции ADO.NET 2.0 (DbProviderFactory, DbConnection, DbCommand...), чтобы уменьшить связь с какой-либо конкретной СУБД. Таким образом, у меня нет доступа к свойству BindByName, если я явно не укажу на OracleCommand, потеряв все преимущества или абстракцию.
  • При использовании ASP.NET SqlDataSource я сам не создаю сам DbCommand, поэтому я не могу установить значение BindByName в true (я мог бы сделать это в событии Selecting, но это действительно боль, чтобы сделать это для каждого SqlDataSource...)

Как мне решить эту проблему? Есть ли параметр BindByNameByDefault где-то? (Я не нашел ничего подобного, но я, возможно, пропустил это...)

Ответ 1

Я думаю, вы можете создать своего собственного провайдера, который использует настройки по умолчанию, которые вы хотите использовать. Вы можете легко создать этого провайдера, наследуя все классы из odp.net, просто настройте некоторые свойства, такие как BindByName.

DbProviderfactory создаст ваши классы вместо обычных классов odp.net.

Ответ 2

Использовать косвенность и наследование! Если вы выполняете доступ к данным через абстрактный класс базы данных, требуется привязка параметров дескриптора реализации базы данных.

public abstract class Database
{
    private readonly DbProviderFactory factory;

    protected Database(DbProviderFactory factory)
    {
        this.factory = factory;
    }

    public virtual DbCommand CreateCommand(String commandText)
    {
        return CreateCommand(CommandType.Text, commandText);
    }

    public virtual DbCommand CreateCommand(CommandType commandType, String commandText)
    {
        DbCommand command = factory.CreateCommand();
        command.CommandType = commandType;
        command.Text = commandText;
        return command;
    }

    public virtual void BindParametersByName(DbCommand command)
    {

    }
}

И выберите создание конкретной реализации Oracle, которая переопределяет создание команды по умолчанию или предоставляет возможность привязывать параметры по имени.

public class OracleDatabase : Database
{
    public OracleDatabase()
        : base(OracleClientFactory.Instance)
    {

    }

    public override DbCommand CreateCommand(CommandType commandType, String commandText)
    {
        DbCommand command = base.CreateCommand(commandType, commandText);
        BindParametersByName(command);
        return command;
    }

    public override void BindParametersByName(DbCommand command)
    {
        ((OracleCommand)command).BindByName = true;
    }
}

Код, основанный на Блок приложений доступа к данным в Предприятие Библиотека.

Ответ 3

Что касается прекращения использования Microsoft ADO.NET для Oracle:

  • Я продолжу использовать его вместо ODP.NET, ваша проблема будет только одной из многочисленных проблем с ним. И, как говорится, он все равно будет доступен в .NET 4.0, хотя и не поддерживается.
  • Если Oracle сумеет сделать этот поставщик непригодным, я, вероятно, поеду с коммерческой альтернативой, например DataDirect ADO.NET Data Provider for Oracle или dotConnect для Oracle, которые полностью интегрируются в платформу ADO.NET. И они уже поддерживают Entity Framework, кстати (я считаю, Oracle заявила, что ODP.NET не будет).

ODP.NET занял слишком много времени.