1

我们的应用程序使用 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);
        }
    }

我不知道这是否是正确的方法或其他一些时尚的解决方法是否已经可用。但它奏效了。

4

2 回答 2

1

我希望以下步骤能给您正确的结果。

用 Oracle.DataAccess.Client 替换 System.Data.OracleClient;和 Oracle.DataAccess.Types

下载并安装最新版本的 Microsoft Enterprise Library 3.1 可以在这里找到:- http://msdn2.microsoft.com/en-us/library/aa480453.aspx

从 Oracle 网站下载并安装 Oracle ODP.Net 您的 DLL 文件应位于:- C:\oracle\product\11.1.0\client_1\odp.net\bin\2.x\Oracle.DataAccess.dll

当它提示您安装源时,请使用复选框。

如果您没有在以下路径 C:\Program Files\Microsoft Enterprise Library 3.1 - May 2007\src 上运行 msi

库的代码存储在以下路径 C:\EntLib3Src\App Blocks

备份原始 src 文件夹以备日后需要时使用 - C:\EntLib3Src\App Blocks\Src

打开解决方案文件 EnterpriseLibrary.sln 并进入 Data Access Application Block 下的数据项目

将 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 注释 - 删除突出显示的错误内容/将其替换为适当的注释希望它现在应该可以编译。

现在通过编译上述项目生成的 DLL 可用于 SqlServer 和 Oracle [ODP.Net]

于 2012-11-13T05:33:02.903 回答
1

对此有点晚了,但我看不出响应者建议使用 EL3.1 的充分理由 这是非常过时的 - 5 是最新版本(在这篇文章之前已经发布了近 2 年)和OP 根据代码示例使用 4.1。将 ODP 与 EL5 一起使用要简单得多(我自己也这样做过,利用 EntlibContrib 项目),虽然我不能说参数大小的任何潜在问题,因为我们不使用 BLOB,但 EntlibContrib 本身允许使用 OracleDbType,所以我认为这可能不是问题。

以防万一有人偶然发现这篇文章想知道如何让 EL5 和 ODP 以最小的麻烦很好地发挥作用,我可以提供详细信息 - 私信我。

于 2013-02-20T16:29:03.027 回答