使用ODP.NET与企业库DAAB连接Oracle

时间:2012-11-06 13:53:24

标签: c# oracle enterprise-library odp.net

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

我的项目中引用了以下程序集:

enter image description here

现在,当我运行应用程序时,Ent Lib DAAP应该使用Oracle.DataAccess.Client,但它仍然通过System.Data.OracleClient连接到oracle db。因此仍有32K的限制。

enter image description here

为什么不使用Oracle数据提供程序,正如我在App.config中明确提到的那样?

在一篇文章中,提到使用以下代码段作为解决方法,

DbProviderFactory providerFactory = DbProviderFactories.GetFactory("Oracle.DataAccess.Client");
Database db = GenericDatabase(connectionString, providerFactory); 

这个似乎有效。

enter image description here

但实例化的数据库是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);
        }
    }

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

2 个答案:

答案 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。