当我的".Net "应用程序试图与oracle数据库建立连接时,我得到了这个错误。
错误说:"这个问题将在安装了32位Oracle客户端组件的64位模式下运行时发生。[但我已经确认了很多次,客户端安装在 "x64 "位而不是 "32 "位。
Date Time: 6/8/2014 10:57:55 AM: System.InvalidOperationException: Attempt to load Oracle client libraries threw BadImageFormatException. This problem will occur when running in 64 bit mode with the 32 bit Oracle client components installed. ---> System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
at System.Data.Common.UnsafeNativeMethods.OCILobCopy2(IntPtr svchp, IntPtr errhp, IntPtr dst_locp, IntPtr src_locp, UInt64 amount, UInt64 dst_offset, UInt64 src_offset)
at System.Data.OracleClient.OCI.DetermineClientVersion()
--- End of inner exception stack trace ---
at System.Data.OracleClient.OCI.DetermineClientVersion()
at System.Data.OracleClient.OracleInternalConnection.OpenOnLocalTransaction(String userName, String password, String serverName, Boolean integratedSecurity, Boolean unicode, Boolean omitOracleConnectionName)
at System.Data.OracleClient.OracleInternalConnection..ctor(OracleConnectionString connectionOptions)
at System.Data.OracleClient.OracleConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options)
at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.OracleClient.OracleConnection.Open()
at CustomizedSetupInstaller.Runscripts.InitializeDBObjects(String connectionString, String dbProvider)
一个解决方案是在你的机器上同时安装x86(32位)和x64的Oracle客户端,那么你的应用程序在哪个架构上运行就不重要。
这里有一个在一台机器上安装x86和x64 Oracle客户端的说明。
假设。Oracle主页被称为 "OraClient11g_home1",客户端版本为11gR2。
可以选择删除任何已安装的Oracle客户端(如果你遇到问题,请参见https://stackoverflow.com/questions/8450726/how-to-uninstall-completely-remove-oracle-11g-client)。
下载并安装Oracle x86客户端,例如安装到C:\Oracle\11.2\Client_x86
中。
下载并安装Oracle x64客户端**到不同的文件夹中,例如到C:\Oracle\11.2\Client_x64
。
打开命令行工具,进入%WINDIR%\System32文件夹,通常是C:\Windows\System32
并创建一个符号链接ora112
到C:\Oracle\11.2Client_x64
文件夹(见下面命令部分)
改变到文件夹%WINDIR%\SysWOW64,通常是C:\Windows\SysWOW64
,并创建一个符号链接ora112
到文件夹C:\Oracle\11.2Client_x86
,(见下文)。
修改PATH
环境变量,用C:\Windows\System32\ora112
替换所有条目,如C:\Oracle\11.2\Client_x86
和C:\Oracle\11.2\Client_x64
,各自的bin
子文件夹。注意:C:Windows\SysWOW64\ora112
必须不在PATH环境中。
如果需要,请将您的ORACLE_HOME
环境变量设置为C:\Windows\System32\ora112
。
打开你的注册表编辑器。将注册表值HKLM\Software\ORACLE\KEY_OraClient11g_home1\ORACLE_HOME
设为C:\Windows\System32\ora112
。
将注册表值HKLM\Software\Wow6432Node\ORACLE\KEY_OraClient11g_home1\ORACLE_HOME
设为C:\Windows\System32\ora112
(不是C:\Windows\SysWOW64\ora112
)。
你已经完成了!现在你可以一起使用x86和x64的Oracle客户端无缝连接,即x86应用程序将加载x86库,x64应用程序加载x64库,而不需要在你的系统上做任何进一步修改。
也许将TNS_ADMIN'环境变量(即注册表中的
TNS_ADMIN'条目)设置为一个共同的位置,例如`TNS_ADMIN=C:\Oracle\Common\network'是一个明智的选择。
创建符号链接的命令。
cd C:\Windows\System32 mklink /d ora112 C:\Oracle\11.2\Client_x64 cd C:\Windows\SysWOW64 mklink /d ora112 C:\Oracle\11.2\Client_x86
。
注释。
两个符号链接必须有相同的名字,例如:ora112
。
尽管它们的名字不同,文件夹C:Windows\System32
包含x64库,而C:Windows\SysWOW64
包含x86(32位)库。不要被混淆了。
在我的情况下,Oracle 11.2 32位客户端 *被安装在我的64位Windows2008 R2操作系统上。
我的解决方案是:在分配给我的ASP.NET应用程序的应用程序池的高级设置中,我将启用32位应用程序设置为True*。
请看下面的独立的.ashx测试脚本,我用它来测试连接到Oracle的能力。在对应用程序池进行修改之前,它的响应是。
[Running as 64-bit] Connection failed.
......而在应用池改变之后。
[Running as 32-bit] Connection succeeded.
TestOracle.ashx - 通过System.Data.OracleClient测试Oracle连接的脚本:。
使用:根据情况改变用户、密码和主机变量。
请注意,这个脚本可以以独立的方式使用,而不影响你的ASP.NET Web应用程序项目文件。只要把它放到你的应用程序文件夹里就可以了。
<%@ WebHandler Language="C#" Class="Handler1" %>
<%@ Assembly Name="System.Data.OracleClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" %>
using System;
using System.Data.OracleClient;
using System.Web;
public class Handler1 : IHttpHandler
{
private static readonly string m_User = "USER";
private static readonly string m_Password = "PASSWORD";
private static readonly string m_Host = "HOST";
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
string result = TestOracleConnection();
context.Response.Write(result);
}
public bool IsReusable
{
get { return false; }
}
private string TestOracleConnection()
{
string result = IntPtr.Size == 8 ?
"[Running as 64-bit]" : "[Running as 32-bit]";
try
{
string connString = String.Format(
"Data Source={0};Password={1};User ID={2};",
m_Host, m_User, m_Password);
OracleConnection oradb = new OracleConnection();
oradb.ConnectionString = connString;
oradb.Open();
oradb.Close();
result += " Connection succeeded.";
}
catch
{
result += " Connection failed.";
}
return result;
}
}
当32位(x86)的dll调用64位的dll时,会发生BadImageFormatException,反之亦然。如果使用AnyCPU作为你的入口可执行文件,那么当在64位机器上运行时,它将以64位运行,但是如果这时调用一个32位的dll,你就会出现异常,这就是为什么AnyCPU并不总是答案。
我倾向于以32位(x86)构建一切,因为我们仍然需要与一些在VB6(32位(x86))中完成的旧组件接口。如果我们使用AnyCPU,64位机的性能可能会更好,但可靠性对我们来说更重要。
我建议你尝试用32位(x86)来构建你的所有组件,除非你在做一些非常密集的事情,否则我怀疑它会有很大的区别。