Связывание параметров запроса по имени с ODP.NET - PullRequest
17 голосов
/ 26 июня 2009

В настоящее время я использую провайдер 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? (Я не нашел ничего подобного, но, возможно, я пропустил это ...)

Ответы [ 3 ]

7 голосов
/ 26 июня 2009

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

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

4 голосов
/ 29 июля 2009

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

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

Код на основе прикладного блока доступа к данным в Enterprise Library .

1 голос
/ 26 июня 2009

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

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

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

...