c# - Enlace de parámetros de consulta por nombre con ODP.NET
oracle ado.net (3)
¡Usa la indirección y la herencia! Si está realizando el acceso a los datos a través de una clase de base de datos abstracta, solicite la implementación de la base de datos manejar el enlace de parámetros.
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 predeterminados o que proporcione la opción de vincular 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 el bloque de aplicación de acceso a datos en la biblioteca de Enterprise .
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 pronto quedará en desuso , en su lugar debería estar usando ODP.NET de Oracle. La razón por la que todavía uso el proveedor de MS es porque ODP.NET enlaza parámetros por posición , no por nombre. Esto realmente puede ser un PITA cuando usas muchos parámetros en una consulta, porque tienes que tener cuidado de agregarlos en el orden correcto, lo que puede conducir fácilmente a errores. También es molesto cuando usa el mismo parámetro varias veces en la misma consulta, por ejemplo:
SELECT A,B,C FROM FOO WHERE X = :PARAM_X OR :PARAM_X = 0
Con ODP.NET, tengo que agregar dos parámetros a OracleCommand
, lo que creo que es estúpido ...
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. Desafortunadamente, esto realmente no me ayuda, porque:
- Se establece en falso por defecto
- Casi nunca uso explícitamente clases concretas de ADO.NET, prefiero usar la capa de abstracción ADO.NET 2.0 (
DbProviderFactory
,DbConnection
,DbCommand
...) para reducir el acoplamiento a cualquier RDBMS específico. Por lo tanto, no tengo acceso a la propiedadBindByName
, a menos queOracleCommand
explícitamente aOracleCommand
, perdiendo todos los beneficios o la abstracción. - Cuando utilizo un ASP.NET SqlDataSource, no creo el DbCommand, por lo que no tengo la oportunidad de establecer
BindByName
en verdadero (podría hacerlo en el evento de Selección, pero realmente es un dolor hacerlo para). cada SqlDataSource ...)
¿Cómo se supone que debo manejar ese problema? ¿Hay una configuración BindByNameByDefault
en algún lugar? (No encontré nada de eso, pero es posible que lo haya perdido ...)
Creo que puede crear su propio proveedor que utiliza los valores predeterminados que desea utilizar. Puede crear ese proveedor fácilmente heredando 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.
En cuanto a la interrupción del proveedor Microsoft ADO .NET para Oracle:
- Seguiré usándolo en lugar de ODP .NET, su problema es solo uno de los numerosos problemas con él. Y a medida que avanza, seguirá estando disponible en .NET 4.0, aunque no es compatible.
- Si Oracle se las arregla para hacer que este proveedor quede inutilizable, probablemente optaré por una alternativa comercial como DataDirect ADO.NET Data Provider para Oracle o dotConnect para Oracle , que se integra completamente en el marco de ADO .NET. Y ya son compatibles con Entity Framework, por cierto (creo que Oracle declaró que ODP .NET no lo haría).
ODP .NET ya me quitó mucho tiempo.