我们的应用程序使用 Enterprise Library DAAB 来支持 oracle 和 sql 数据库。
存储过程之一是将图像上传到表。它是一个 BLOB 字段,参数设置为 DbType.Binary。
此功能对 SQL 没有任何问题,但是当谈到 Oracle 时,我遇到了 32K 参数大小限制问题。
正如 SO 中所建议的,我将代码移至 ODP.NET,但我仍然面临同样的问题。
我的 App.config 文件设置:
<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>
在我的应用程序代码中,我使用企业库来访问数据库
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);
我的项目中引用了以下程序集:
现在当我运行应用程序时,Ent Lib DAAP 应该使用 Oracle.DataAccess.Client,但它仍然通过 System.Data.OracleClient 连接到 oracle db。所以 32K 限制仍然存在。
为什么它不使用我在 App.config 中明确提到的 Oracle 数据提供程序?
在一篇文章中,提到使用以下代码段作为解决方法,
DbProviderFactory providerFactory = DbProviderFactories.GetFactory("Oracle.DataAccess.Client");
Database db = GenericDatabase(connectionString, providerFactory);
这似乎工作。
但是实例化的数据库是 GenericDatabase 而不是 OracleDatabase,这可能就是为什么当文件大小超过 32K 时,即使这个工作仍然抛出异常。
如何将 ODP.NET 与企业库一起使用以解决 32K 大小限制问题?
已解决:
我跟着hridya走过。正如他所提到的,有 XML 注释错误,可以关闭(看这里)。还有一些命名空间冲突通过选择 Oracle.DataAccess.Client 得到解决。经过这些,它编译成功。
这是我为测试更改而制作的示例应用程序的代码片段。(示例解决方案现在引用新编译的 Data 和 Common dll。)
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);
我检查了命令对象,现在它是 Oracle.DataAccess.Client.OracleCommand 类型,而之前它是 System.Data.OracleClient.OracleCommand。
请记住,因为我已经修改了 DAAB 以使用 ODP.NET,所以我不需要使用 providerMappings 标记在配置文件中显式设置提供程序。
但是当文件大小超过 32K 时,我仍然会遇到相同的错误,逐行进入代码显示问题出在 DbType.Binary 上。它没有更改为正确的 OracleDbType。
为了使它工作,我在 Enterprise Lib 的数据项目中添加了一个代码修复程序。
文件:\Oracle\OracleDatabase.cs
方法:添加参数
原始代码:
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);
}
}
为 DbType.Binary 添加了条件
修改代码:
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);
}
}
我不知道这是否是正确的方法或其他一些时尚的解决方法是否已经可用。但它奏效了。