SPRNET-1571 SPRNET-1572 set OracleCommand's BindByName to true

* add native ODP.NET 12 provider
* add managed ODP.NET 12 provider
This commit is contained in:
Marko Lahma
2014-03-14 13:19:59 +02:00
parent 0311d3694d
commit e9ade58ee7
6 changed files with 275 additions and 64 deletions

View File

@@ -20,6 +20,7 @@
using System;
using System.Data;
using Spring.Expressions;
using Spring.Reflection.Dynamic;
using Spring.Util;
@@ -32,12 +33,13 @@ namespace Spring.Data.Common
public class DbProvider : IDbProvider
{
private string connectionString;
private IDbMetadata dbMetadata;
private IDynamicConstructor newCommand;
private IDynamicConstructor newConnection;
private IDynamicConstructor newCommandBuilder;
private IDynamicConstructor newDataAdapter;
private IDynamicConstructor newParameter;
private readonly IDbMetadata dbMetadata;
private readonly IDynamicConstructor newCommand;
private readonly IDynamicProperty commandBindByName;
private readonly IDynamicConstructor newConnection;
private readonly IDynamicConstructor newCommandBuilder;
private readonly IDynamicConstructor newDataAdapter;
private readonly IDynamicConstructor newParameter;
/// <summary>
/// Initializes a new instance of the <see cref="DbProvider"/> class.
@@ -47,6 +49,14 @@ namespace Spring.Data.Common
{
this.dbMetadata = dbMetadata;
newCommand = DynamicConstructor.Create(dbMetadata.CommandType.GetConstructor(Type.EmptyTypes));
// Oracle needs custom bind by name property set to true as it's false by default
var bindByNameProperty = dbMetadata.CommandType.GetProperty("BindByName");
if (bindByNameProperty != null && bindByNameProperty.CanWrite)
{
commandBindByName = DynamicProperty.Create(bindByNameProperty);
}
newConnection = DynamicConstructor.Create(dbMetadata.ConnectionType.GetConstructor(Type.EmptyTypes));
newCommandBuilder = DynamicConstructor.Create(dbMetadata.CommandBuilderType.GetConstructor(Type.EmptyTypes));
newDataAdapter = DynamicConstructor.Create(dbMetadata.DataAdapterType.GetConstructor(Type.EmptyTypes));
@@ -60,7 +70,12 @@ namespace Spring.Data.Common
/// <returns>An new <see cref="IDbCommand"/></returns>
public IDbCommand CreateCommand()
{
return newCommand.Invoke(ObjectUtils.EmptyObjects) as IDbCommand;
var command = newCommand.Invoke(ObjectUtils.EmptyObjects) as IDbCommand;
if (command != null && commandBindByName != null)
{
commandBindByName.SetValue(command, dbMetadata.BindByName);
}
return command;
}
/// <summary>
@@ -188,20 +203,16 @@ namespace Spring.Data.Common
/// <returns>The provider specific error code</returns>
public string ExtractError(Exception e)
{
if (!StringUtils.IsNullOrEmpty(dbMetadata.ErrorCodeExceptionExpression))
{
return ExpressionEvaluator.GetValue(e, dbMetadata.ErrorCodeExceptionExpression).ToString();
}
}
else
{
return "Could not extract error code exception type." + e.GetType();
return "Could not extract error code exception type." + e.GetType();
}
}
/// <summary>
/// Determines whether the provided exception is in fact related
/// to database access. This can be provider dependent in .NET 1.1 since
@@ -215,7 +226,6 @@ namespace Spring.Data.Common
/// </returns>
public bool IsDataAccessException(Exception e)
{
if (e is System.Data.Common.DbException)
{
return true;
@@ -225,21 +235,5 @@ namespace Spring.Data.Common
return false;
}
}
/// <summary>
/// Determines whether is data access exception in .NET 1.1 for the specified exception.
/// </summary>
/// <param name="e">The candidate exception.</param>
/// <returns>
/// <c>true</c> if is data access exception in .NET 1.1 for the specified exception; otherwise, <c>false</c>.
/// </returns>
private bool IsDataAccessExceptionBCL11(Exception e)
{
if (e == null)
{
return false;
}
return e.GetType().IsAssignableFrom(DbMetadata.ExceptionType);
}
}
}
}

View File

@@ -500,7 +500,6 @@
</object>
</constructor-arg>
</object>
<object id="OracleODP-11-4.0" type="Spring.Data.Common.DbProvider, Spring.Data" singleton="false">
<constructor-arg name="dbMetaData">
@@ -551,11 +550,163 @@
</property>
</object>
</constructor-arg>
</object>
</object>
<object id="OracleODP-12-2.0" type="Spring.Data.Common.DbProvider, Spring.Data" singleton="false">
<constructor-arg name="dbMetaData">
<object type="Spring.Data.Common.DbMetadata">
<constructor-arg name="productName" value="Oracle, Oracle provider V2.121.1.0" />
<constructor-arg name="assemblyName" value="Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="connectionType" value="Oracle.DataAccess.Client.OracleConnection, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandType" value="Oracle.DataAccess.Client.OracleCommand, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="parameterType" value="Oracle.DataAccess.Client.OracleParameter, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="dataAdapterType" value="Oracle.DataAccess.Client.OracleDataAdapter, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandBuilderType" value="Oracle.DataAccess.Client.OracleCommandBuilder, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandBuilderDeriveParametersMethod" value="DeriveParameters"/>
<constructor-arg name="parameterDbType" value="Oracle.DataAccess.Client.OracleDbType, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="parameterDbTypeProperty" value="OracleDbType"/>
<constructor-arg name="parameterIsNullableProperty" value="IsNullable"/>
<constructor-arg name="parameterNamePrefix" value=":"/>
<constructor-arg name="exceptionType" value="Oracle.DataAccess.Client.OracleException, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="useParameterNamePrefixInParameterCollection" value="false"/>
<constructor-arg name="useParameterPrefixInSql" value="true"/>
<constructor-arg name="bindByName" value="true"/>
<!-- this is only true for .net 1.1 kept it here just in case we want to revert back to this strategy for
obtaining error codes-->
<constructor-arg name="errorCodeExceptionExpression" value="Number.ToString()"/>
<property name="ErrorCodes.BadSqlGrammarCodes">
<value>900,903,904,917,936,942,17006</value>
</property>
<property name="ErrorCodes.InvalidResultSetAccessCodes">
<value>17003</value>
</property>
<property name="ErrorCodes.DuplicateKeyCodes">
<value>1</value>
</property>
<property name="ErrorCodes.DataAccessResourceFailureCodes">
<value>17002,17447</value>
</property>
<property name="ErrorCodes.DataIntegrityViolationCodes">
<value>1,1400,1722,2291,2292</value>
</property>
<property name="ErrorCodes.CannotAcquireLockCodes">
<value>54</value>
</property>
<property name="ErrorCodes.CannotSerializeTransactionCodes">
<value>8177</value>
</property>
<property name="ErrorCodes.DeadlockLoserCodes">
<value>60</value>
</property>
</object>
</constructor-arg>
</object>
<object id="OracleODP-12-4.0" type="Spring.Data.Common.DbProvider, Spring.Data" singleton="false">
<constructor-arg name="dbMetaData">
<object type="Spring.Data.Common.DbMetadata">
<constructor-arg name="productName" value="Oracle, Oracle provider V4.121.1.0" />
<constructor-arg name="assemblyName" value="Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="connectionType" value="Oracle.DataAccess.Client.OracleConnection, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandType" value="Oracle.DataAccess.Client.OracleCommand, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="parameterType" value="Oracle.DataAccess.Client.OracleParameter, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="dataAdapterType" value="Oracle.DataAccess.Client.OracleDataAdapter, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandBuilderType" value="Oracle.DataAccess.Client.OracleCommandBuilder, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandBuilderDeriveParametersMethod" value="DeriveParameters"/>
<constructor-arg name="parameterDbType" value="Oracle.DataAccess.Client.OracleDbType, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="parameterDbTypeProperty" value="OracleDbType"/>
<constructor-arg name="parameterIsNullableProperty" value="IsNullable"/>
<constructor-arg name="parameterNamePrefix" value=":"/>
<constructor-arg name="exceptionType" value="Oracle.DataAccess.Client.OracleException, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="useParameterNamePrefixInParameterCollection" value="false"/>
<constructor-arg name="useParameterPrefixInSql" value="true"/>
<constructor-arg name="bindByName" value="true"/>
<!-- this is only true for .net 1.1 kept it here just in case we want to revert back to this strategy for
obtaining error codes-->
<constructor-arg name="errorCodeExceptionExpression" value="Number.ToString()"/>
<property name="ErrorCodes.BadSqlGrammarCodes">
<value>900,903,904,917,936,942,17006</value>
</property>
<property name="ErrorCodes.InvalidResultSetAccessCodes">
<value>17003</value>
</property>
<property name="ErrorCodes.DuplicateKeyCodes">
<value>1</value>
</property>
<property name="ErrorCodes.DataAccessResourceFailureCodes">
<value>17002,17447</value>
</property>
<property name="ErrorCodes.DataIntegrityViolationCodes">
<value>1,1400,1722,2291,2292</value>
</property>
<property name="ErrorCodes.CannotAcquireLockCodes">
<value>54</value>
</property>
<property name="ErrorCodes.CannotSerializeTransactionCodes">
<value>8177</value>
</property>
<property name="ErrorCodes.DeadlockLoserCodes">
<value>60</value>
</property>
</object>
</constructor-arg>
</object>
<object id="OracleODP-Managed-12-4.0" type="Spring.Data.Common.DbProvider, Spring.Data" singleton="false">
<constructor-arg name="dbMetaData">
<object type="Spring.Data.Common.DbMetadata">
<constructor-arg name="productName" value="Oracle, Oracle Managed provider V4.121.1.0" />
<constructor-arg name="assemblyName" value="Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="connectionType" value="Oracle.ManagedDataAccess.Client.OracleConnection, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandType" value="Oracle.ManagedDataAccess.Client.OracleCommand, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="parameterType" value="Oracle.ManagedDataAccess.Client.OracleParameter, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="dataAdapterType" value="Oracle.ManagedDataAccess.Client.OracleDataAdapter, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandBuilderType" value="Oracle.ManagedDataAccess.Client.OracleCommandBuilder, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandBuilderDeriveParametersMethod" value="DeriveParameters"/>
<constructor-arg name="parameterDbType" value="Oracle.ManagedDataAccess.Client.OracleDbType, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="parameterDbTypeProperty" value="OracleDbType"/>
<constructor-arg name="parameterIsNullableProperty" value="IsNullable"/>
<constructor-arg name="parameterNamePrefix" value=":"/>
<constructor-arg name="exceptionType" value="Oracle.ManagedDataAccess.Client.OracleException, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="useParameterNamePrefixInParameterCollection" value="false"/>
<constructor-arg name="useParameterPrefixInSql" value="true"/>
<constructor-arg name="bindByName" value="true"/>
<!-- this is only true for .net 1.1 kept it here just in case we want to revert back to this strategy for
obtaining error codes-->
<constructor-arg name="errorCodeExceptionExpression" value="Number.ToString()"/>
<property name="ErrorCodes.BadSqlGrammarCodes">
<value>900,903,904,917,936,942,17006</value>
</property>
<property name="ErrorCodes.InvalidResultSetAccessCodes">
<value>17003</value>
</property>
<property name="ErrorCodes.DuplicateKeyCodes">
<value>1</value>
</property>
<property name="ErrorCodes.DataAccessResourceFailureCodes">
<value>17002,17447</value>
</property>
<property name="ErrorCodes.DataIntegrityViolationCodes">
<value>1,1400,1722,2291,2292</value>
</property>
<property name="ErrorCodes.CannotAcquireLockCodes">
<value>54</value>
</property>
<property name="ErrorCodes.CannotSerializeTransactionCodes">
<value>8177</value>
</property>
<property name="ErrorCodes.DeadlockLoserCodes">
<value>60</value>
</property>
</object>
</constructor-arg>
</object>
<!-- My Sql -->
<!-- Connector/NET 1.0 -->