2009-06-25 11 views
16

Actualmente estoy usando el proveedor Microsoft ADO.NET para Oracle (System.Data.OracleClient). Soy consciente de que ciertamente no es el mejor proveedor de Oracle disponible y que will soon be deprecated, debería estar usando Oracle ODP.NET en su lugar. La razón por la que todavía uso el proveedor MS es porque ODP.NET vincula los parámetros por posición, no por su nombre. Esto realmente puede ser un PITA cuando usa muchos parámetros en una consulta, porque debe tener cuidado de agregarlos en el orden correcto, lo que puede conducir fácilmente a errores. También es molesto cuando se utiliza el mismo parámetro varias veces en la misma consulta, por ejemplo:Enlazar parámetros de consulta por nombre con ODP.NET

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

Con ODP.NET, tengo que añadir dos parámetros a la OracleCommand, que creo que es estúpida ...

OracleCommand de ODP.NET tiene una propiedad para cambiar ese comportamiento predeterminado: BindByName. Cuando se establece en verdadero, los parámetros están vinculados por nombre, que es lo que quiero. Por desgracia, esto realmente no me ayuda, porque:

  • Se establece en false por defecto
  • que casi nunca uso de ADO.NET clases concretas de forma explícita, yo prefiero usar ADO.NET 2.0 capa de abstracción (DbProviderFactory , DbConnection, DbCommand ...) para reducir el acoplamiento a cualquier RDBMS específico. Así que no tengo acceso a la propiedad BindByName, a menos que la use explícitamente en OracleCommand, perdiendo todos los beneficios o la abstracción.
  • Cuando uso un ASP.NET SqlDataSource, no creo el DbCommand yo mismo, así que no tengo la oportunidad de establecer BindByName en verdadero (podría hacerlo en el evento de selección, pero realmente me duele hágalo por cada SqlDataSource ...)

¿Cómo se supone que debo manejar este problema? ¿Hay un ajuste BindByNameByDefault en alguna parte? (No encontré nada de eso, pero es posible que me lo haya perdido ...)

+0

¡Acabo de perder 3 horas debido a esta "función"! – Grzenio

Respuesta

7

Creo que puede crear su propio proveedor que utiliza los valores predeterminados que desea utilizar. Puede crear ese proveedor fácilmente al heredar todas las clases de odp.net, simplemente ajuste algunas propiedades como BindByName.

El DbProviderfactory creará sus clases en lugar de las clases normales de odp.net.

+0

¡Buena idea, gracias! Creo que intentaré eso –

+2

OK, parece factible, pero no muy sencillo ... la mayoría de las clases ODP.NET están selladas, por lo que no puedo heredar de ellas para anular los métodos, y de acuerdo con Reflector hay muchos lugares donde El constructor OracleCommand se llama explícitamente ... De todos modos, no se me ocurre ninguna solución mejor, así que acepto su respuesta. Gracias ! –

1

En cuanto a la suspensión del proveedor de Microsoft ADO .NET para Oracle:

  • voy a entrar en usarlo en lugar de PAO .NET, su problema de ser sólo uno de los numerosos problemas con él. Y a medida que avanza, seguirá estando disponible en .NET 4.0, aunque no sea compatible.
  • Si Oracle logra inutilizar este proveedor, probablemente vaya con una alternativa comercial como DataDirect ADO.NET Data Provider for Oracle o dotConnect for Oracle, que se integra completamente en ADO .NET framework. Y, por cierto, ya respaldan el Marco de la Entidad (creo que Oracle afirmó que ODP .NET no lo haría).

ODP .NET tomó demasiado tiempo de mi parte.

+0

Probablemente tenga razón sobre los proveedores de terceros, pero no son gratuitos, por lo que no estoy seguro de poder convencer a mi empleador para que los compre ... Sin embargo, el soporte de Entity Framework es un argumento serio para poner en la balanza . No puedo entender por qué Oracle no lo implementa en ODP.NET ... –

+0

Recomiendo encarecidamente dotConnect for Oracle. Vale cada dólar que pagas por él. – Konamiman

+0

Oracle ha comenzado a apoyar Entity Framework en realidad, hay una versión beta de ODP.net con soporte de EF y Linq en este momento. – Tridus

4

¡Utilice la indirección y la herencia! Si está realizando acceso a datos a través de una clase de base de datos abstracta, requiera el enlace del parámetro del identificador de la implementación de la base de datos.

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

    } 
} 

Y elija crear una implementación específica de Oracle que anule la creación de comandos predeterminada o proporcione la opción de enlazar parámetros por nombre.

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

Código basado en la Data Access Application Block en el Enterprise Library.

+0

Esto es muy similar a lo que terminé haciendo para un proyecto. La clase OracleDatabase también proporciona un buen punto de extensión para agregar métodos de conveniencia que la implementación predeterminada de ODP.NET no proporciona. – CodingWithSpike

+0

Aunque esta solución es perfecta para el código C#, no ayuda en el caso de ASP.NET SqlDataSource: tengo que especificar un proveedor ADO.NET, no una capa de acceso a datos personalizada ... –

+0

@Thomas Levesque No estoy familiarizado con SqlDataSource, pero parece que puedes heredar de DataSourceControl y reconstruir tu propio OracleDataSource ... ¿suena divertido? –

Cuestiones relacionadas