Our application is using Enterprise Library DAAB to support both oracle and sql databases.
One of the Stored Procedure is for uploading Image to Table. It's a BLOB field and the parameter is set to DbType.Binary.
This functionality works without any problem for SQL, But when comes to Oracle I hit the 32K parameter size limit issue.
As suggested in SO, I moved the code to ODP.NET, but I am still facing the same problem.
My App.config file setting:
<configuration>
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<dataConfiguration defaultDatabase="Oracle">
<providerMappings>
<add databaseType="Microsoft.Practices.EnterpriseLibrary.Data.Oracle.OracleDatabase, Microsoft.Practices.EnterpriseLibrary.Data, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
name="Oracle.DataAccess.Client" />
</providerMappings>
</dataConfiguration>
<connectionStrings>
<add name="Oracle" connectionString="Data Source=MYORACSER;USER ID=UNAME;PASSWORD=MYPWD;"
providerName="Oracle.DataAccess.Client" />
</connectionStrings>
In my application code I am using enterprise library to access the DB
Database db = DatabaseFactory.CreateDatabase();
DbCommand cmd = db.GetStoredProcCommand(spName);
cmd.CommandType = CommandType.StoredProcedure;
db.AddInParameter(cmd, "DOCIMAGE", DbType.Binary, GetByteArrayFromFile(filePath));
db.AddOutParameter(cmd, "return_value", DbType.Int32, 128);
int row = db.ExecuteNonQuery(cmd);
I have the following assemblies referenced in my project:
Now when I run the application, Ent Lib DAAP is supposed to be using Oracle.DataAccess.Client, but It is still wired to oracle db through System.Data.OracleClient. So 32K limit is still there.
Why it is not using Oracle Data Provider as I have clearly mentioned in App.config?
In one post, It is mentioned to use the following snippet as a workaround,
DbProviderFactory providerFactory = DbProviderFactories.GetFactory("Oracle.DataAccess.Client");
Database db = GenericDatabase(connectionString, providerFactory);
This one seems working.
But the instantiated Database is of GenericDatabase instead of OracleDatabase, may be that's why even this work around still throwing exception when file size is over 32K.
How do I use ODP.NET with Enterprise Library for 32K size limit issue?
RESOLVED:
I followed hridya walk through. As he mentioned there were XML comment errors, which can be turned off (Look here). Also there were couple of namespace conflicts which were resolved by choosing Oracle.DataAccess.Client. After these, It compiled successfully.
Here is my code snippet from the sample application I made it to test the changes. (The sample solution now references new compiled Data and Common dlls.)
Database db = DatabaseFactory.CreateDatabase();
DbCommand cmd = db.GetStoredProcCommand(sqlCode);
cmd.CommandType = CommandType.StoredProcedure;
db.AddInParameter(cmd, "DOCIMAGE", DbType.Binary, GetByteArrayFromFile(filePath));
db.AddOutParameter(cmd, "return_value", DbType.Int32, 128);
int rowID = db.ExecuteNonQuery(cmd);
I checked command object, now it is of type Oracle.DataAccess.Client.OracleCommand whereas previously it was System.Data.OracleClient.OracleCommand.
Remember since I have already modified the DAAB to use ODP.NET, I don't need to set the provider explicitly in the config file using providerMappings tag.
But I still get the same error when the file size exceeds 32K, Stepping into the code line by line revealed that the problem is with the DbType.Binary. It didn't get changed to proper OracleDbType.
To make it work I have added one more code fix in Enterprise Lib's Data Project.
File: \Oracle\OracleDatabase.cs
Method: AddParameter
Original code:
public override void AddParameter(DbCommand command, string name, DbType dbType, int size,
ParameterDirection direction, bool nullable, byte precision, byte scale, string sourceColumn,
DataRowVersion sourceVersion, object value)
{
if (DbType.Guid.Equals(dbType))
{
object convertedValue = ConvertGuidToByteArray(value);
AddParameter((OracleCommand)command, name, OracleDbType.Raw, 16, direction, nullable, precision,
scale, sourceColumn, sourceVersion, convertedValue);
RegisterParameterType(command, name, dbType);
}
else
{
base.AddParameter(command, name, dbType, size, direction, nullable, precision, scale,
sourceColumn, sourceVersion, value);
}
}
Added condition for DbType.Binary
Modified Code:
public override void AddParameter(DbCommand command, string name, DbType dbType, int size,
ParameterDirection direction, bool nullable, byte precision, byte scale, string sourceColumn,
DataRowVersion sourceVersion, object value)
{
if (DbType.Guid.Equals(dbType))
{
object convertedValue = ConvertGuidToByteArray(value);
AddParameter((OracleCommand)command, name, OracleDbType.Raw, 16, direction, nullable, precision,
scale, sourceColumn, sourceVersion, convertedValue);
RegisterParameterType(command, name, dbType);
}
else if(DbType.Binary.Equals(dbType))
{
AddParameter((OracleCommand)command, name, OracleDbType.Blob, size, direction, nullable, precision,
scale, sourceColumn, sourceVersion, value);
}
else
{
base.AddParameter(command, name, dbType, size, direction, nullable, precision, scale,
sourceColumn, sourceVersion, value);
}
}
I don't know If this the right way to do it or some other sleek workaround is already available. But it worked.