我们的应用程序使用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的限制。
为什么不使用Oracle数据提供程序,正如我在App.config中明确提到的那样?
在一篇文章中,提到使用以下代码段作为解决方法,
DbProviderFactory providerFactory = DbProviderFactories.GetFactory("Oracle.DataAccess.Client");
Database db = GenericDatabase(connectionString, providerFactory);
这个似乎有效。
但实例化的数据库是GenericDatabase而不是OracleDatabase,这可能就是为什么即使这个工作仍然在文件大小超过32K时抛出异常。
如何将ODP.NET与企业库一起用于32K大小限制问题?
已解决:
我跟着 hridya 走了过来。 正如他所提到的,XML注释错误可以被关闭(Look here)。 还有一些命名空间冲突通过选择Oracle.DataAccess.Client来解决。在这之后,它成功编译。
以下是我用来测试更改的示例应用程序的代码片段。 (示例解决方案现在引用新编译的数据和公共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
方法: AddParameter
原始代码:
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);
}
}
我不知道如果这是正确的方法或其他一些光滑的解决方法已经可用。 但它奏效了。
答案 0 :(得分:1)
我希望以下步骤能为您提供正确的结果。
用Oracle.DataAccess.Client替换System.Data.OracleClient;和Oracle.DataAccess.Types
下载并安装最新版本的Microsoft Enterprise Library ver 3.1可在此处找到: - http://msdn2.microsoft.com/en-us/library/aa480453.aspx
从Oracle网站下载并安装Oracle ODP.Net您的DLL文件应该是: - C:\ ORACLE \产品\ 11.1.0 \的Client_1 \ odp.net \ BIN \ 2.x的\ Oracle.DataAccess.dll
当提示您安装源时,请使用复选框。
如果没有,则在以下路径上运行msi C:\ Program Files \ Microsoft Enterprise Library 3.1 - 2007年5月\ src
库的代码存储在以下路径C:\ EntLib3Src \ App Blocks
备份原始src文件夹,以备日后需要时使用 - C:\ EntLib3Src \ App Blocks \ Src
打开解决方案文件EnterpriseLibrary.sln并转到数据访问应用程序块
下的数据项目将Oracle.DataAccess.dll引用添加到数据项目。您的DLL文件应该是: - C:\ oracle \ product \ 11.1.0 \ client_1 \ odp.net \ bin \ 2.x \ Oracle.DataAccess.dll
搜索并替换以下[您可以下载并使用本文附带的更新的DLL]
文件: - C:\ EntLib3Src \ App Blocks \ Src \ Data \ Oracle \ OracleDatabase.cs
文件: - C:\ EntLib3Src \ App Blocks \ Src \ Data \ DatabaseConfigurationView.cs
文件: - C:\ EntLib3Src \ App Blocks \ Src \ Data \ Oracle \ OracleDataReaderWrapper.cs
查找: - using System.Data.OracleClient;
替换为: - using Oracle.DataAccess.Client; using Oracle.DataAccess.Types;
文件: - C:\ EntLib3Src \ App Blocks \ Src \ Data \ Configuration \ DbProviderMapping.cs类: - DbProviderMapping
查找: - System.Data.OracleClient
替换为: - Oracle.DataAccess.Client
文件: - C:\ EntLib3Src \ App Blocks \ Src \ Data \ Configuration \ Manageability \
ConnectionStringsManageabilityProvider.cs
方法: - AddAdministrativeTemplateDirectives
查找: - System.Data.OracleClient
替换为: - Oracle.DataAccess.Client
文件: - C:\ EntLib3Src \ App Blocks \ Src \ Data \ Oracle \ OracleDatabase.cs
方法: - AddParameter
查找: - public void AddParameter(OracleCommand command, string name, OracleType oracleType, int size, ParameterDirection direction, bool nullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
替换为: - public void AddParameter(OracleCommand command, string name, OracleDbType oracleType, int size, ParameterDirection direction, bool nullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
原因: - OracleType替换为OracleDbType作为第三个参数,因为odp.net API中的类型名称
文件: - C:\ EntLib3Src \ App Blocks \ Src \ Data \ Oracle \ OracleDatabase.cs
删除: - [OraclePermission(SecurityAction.Demand)]
-
如果有人请回复反馈会议
,请不知道该怎么办?文件: - C:\ EntLib3Src \ App Blocks \ Src \ Data \ Oracle \ OracleDatabase.cs
查找: - OracleType.Raw
替换为: - OracleDbType.Raw
查找: - param.OracleType
替换为: - param.OracleDbType
查找: - OracleType.Cursor
替换为: - OracleDbType.RefCursor
查找: - parameter.OracleType
替换为: - parameter.OracleDbType
立即编译,如果出现错误,请执行以下警告:错误:XML注释 - 删除突出显示的错误内容/用approp注释替换它希望它现在可以正常编译。
现在,通过编译上述项目生成的DLL可以用于SqlServer和Oracle [ODP.Net]
答案 1 :(得分:1)
有点迟到了,但是我看不出有什么理由说明为什么响应者建议使用EL3.1那是非常过时的 - 5是最新版本(并且在这篇文章之前已经推出了将近2年)并且OP根据代码示例使用4.1。将ODP与EL5一起使用要简单得多(我自己这样做,利用EntlibContrib项目)虽然我不能说任何参数大小的潜在问题因为我们不使用BLOB,但EntlibContrib本身允许使用OracleDbType所以我认为这可能不是问题。
以防万一有人在这篇文章中发现,想知道如何让EL5和ODP玩得很好,我可以提供细节 - PM me。