如何使 odp.net 12c 与其他 oracle 客户端一起工作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28638664/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to make odp.net 12c to work with other oracle client
提问by Shawn
I have oracle 10g client(full) and 11g instant client installed on my machine. I am trying to use ODP.NET 12c. Here is what I did.
我的机器上安装了 oracle 10g 客户端(完整版)和 11g 即时客户端。我正在尝试使用 ODP.NET 12c。这是我所做的。
- Added Oracle.DataAccess.dll to References.
- Copied OraOps12.dll to the folder where my executable is.
- 将 Oracle.DataAccess.dll 添加到参考。
- 将 OraOps12.dll 复制到我的可执行文件所在的文件夹。
When running I got "Unable to load DLL 'OraOps12.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)".
运行时出现“无法加载 DLL 'OraOps12.dll':找不到指定的模块。(HRESULT 异常:0x8007007E)”。
I think it could be due to dependency issue. So I further copied 12c's
我认为这可能是由于依赖性问题。所以我进一步复制了12c的
- oci.dll
- oraociei12.dll
- orannzsbb12.dll
- oci.dll
- oraociei12.dll
- orannzsbb12.dll
I then still got other dependency errors. I don't want to copy the whole InstantClient though.
然后我仍然遇到其他依赖错误。不过,我不想复制整个 InstantClient。
My goal is to get the app to work with other versions of Oracle client. Our customers have different version of Oracle client installed. So any way to get the app (ODAC12c) work with customers' current version of Oracle client without having to install 12c client?
我的目标是让应用程序与其他版本的 Oracle 客户端一起使用。我们的客户安装了不同版本的 Oracle 客户端。那么有什么方法可以让应用程序 (ODAC12c) 与客户当前版本的 Oracle 客户端一起使用而无需安装 12c 客户端?
Thanks,
谢谢,
Update: I forgot to mention a few things
更新:我忘了提几件事
my ODAC is 32bit and I compiled my app on x86.
I didn't use Oracle.ManagedDataAccess.dll because it does not include BULKCOPY classs. If anyone knows a version of Oracle.ManagedDataAccess.dll that includes bulkcopy class please let me know.
Our customers already has different versions of Oracle client installed for other apps and they don't want to change their environment just for this new app. So my goal becomes to make one version of ODAC in my app work with different versions of existing Oracle client (each customer environment is different). Is this possible and if yes, how?
我的 ODAC 是 32 位,我在 x86 上编译了我的应用程序。
我没有使用 Oracle.ManagedDataAccess.dll,因为它不包含 BULKCOPY 类。如果有人知道包含批量复制类的 Oracle.ManagedDataAccess.dll 版本,请告诉我。
我们的客户已经为其他应用程序安装了不同版本的 Oracle 客户端,他们不想仅仅为了这个新应用程序而改变他们的环境。所以我的目标是让我的应用程序中的一个版本的 ODAC 与现有 Oracle 客户端的不同版本一起工作(每个客户环境都不同)。这是可能的,如果是,如何?
采纳答案by b_levitt
You know, I just spent 5 minutes looking for the guy that I remember attempting this before...and it turned out to be you shawn ;).
你知道,我只花了 5 分钟寻找我记得之前尝试过这个的人......结果是你 shawn ;)。
Honestly, to rely on what the client has installed is a crap-shoot. I would use the full xcopy package, get it working, and then work backwards, deleting what is not needed.
老实说,依赖客户端安装的东西是废话。我会使用完整的 xcopy 包,让它工作,然后向后工作,删除不需要的东西。
- Don't run the install.bat that comes with it. Doing so adds registry entries that aid in locating the unmanaged binaries, but you also risk messing with a client installed copy.
- Drop the whole xcopy install into your app's folder as a subfolder.
- Instead, set the DllPath to this new subfolder
- 不要运行它附带的 install.bat。这样做会添加有助于定位非托管二进制文件的注册表项,但您也有可能弄乱客户端安装的副本。
- 将整个 xcopy 安装作为子文件夹放入您的应用程序文件夹中。
- 相反,将 DllPath 设置为这个新的子文件夹
Example:
例子:
<oracle.dataaccess.client>
<settings>
<add name="DllPath" value="C:\app\user\product.1.0\client_1\BIN"/>
- Then set the Oracle_Home environment variable
- 然后设置 Oracle_Home 环境变量
Example:
例子:
Environment.SetEnvironmentVariable("ORACLE_HOME", @"C:\app\user\product.1.0\client_1\");
This article does something similar: http://dbaportal.eu/2013/02/22/true-xcopy-runtime-for-oracle-odp-net-application/
这篇文章做了类似的事情:http: //dbaportal.eu/2013/02/22/true-xcopy-runtime-for-oracle-odp-net-application/
He even adds a policy to redirect in case he has referenced projects that reference a particular version of Oracle.DataAccess.dll
他甚至添加了一个重定向策略,以防他引用了引用特定版本的 Oracle.DataAccess.dll 的项目
He adds his oracle home with a batch file though. The part I'm not so sure of is that he also adds his new xcopy install to the path with that same batch file. DllPath should take care of that, but if I'm wrong, you can also do that at runtime:
不过,他使用批处理文件添加了他的 oracle 主页。我不太确定的部分是他还将他的新 xcopy 安装添加到具有相同批处理文件的路径中。DllPath 应该解决这个问题,但如果我错了,你也可以在运行时这样做:
Environment.SetEnvironmentVariable("PATH", @"C:\app\user\product.1.0\client_1\BIN");
From here, I'd setup some basic unit tests using all the ODP.net functionality you are using and get some positive tests and then work backwards - start deleting what you don't need, running your tests each time. You might be able to use sysinternals procexp to show loaded dlls (or procmon to show access to the files). Just loading your tests might be enough to lock the files so you can delete all the ones that aren't locked.
从这里开始,我将使用您正在使用的所有 ODP.net 功能设置一些基本的单元测试,并进行一些积极的测试,然后向后工作 - 开始删除您不需要的内容,每次都运行您的测试。您也许可以使用 sysinternals procexp 来显示加载的 dll(或 procmon 来显示对文件的访问)。仅加载您的测试可能足以锁定文件,以便您可以删除所有未锁定的文件。
I'm not sure doing this is supported. Then again Oracle does list "the current application's directory" in the unmanaged search order so they didn't close the door either.
我不确定这样做是否受支持。然后 Oracle 再次按照非托管搜索顺序列出“当前应用程序的目录”,因此他们也没有关门。
EDIT: Found one of the links of other people doing this: http://alderprogs.blogspot.com/2009/04/deploying-odpnet-with-oracle-instant.html
编辑:找到其他人这样做的链接之一:http: //alderprogs.blogspot.com/2009/04/deploying-odpnet-with-oracle-instant.html
I'm not sure why but they download the instant client separately (it's already part of the xcopy package).
我不知道为什么,但他们单独下载了即时客户端(它已经是 xcopy 包的一部分)。
EDIT 4/15/2016: If you're reading this these days note two things. 1) I don't think setting the environment variables are necessary if you are already setting DllPath. 2) I don't think this is worth doing when the managed provider now only requires one or two dlls.
2016 年 4 月 15 日编辑:如果您最近正在阅读本文,请注意两件事。1)如果您已经设置了 DllPath,我认为不需要设置环境变量。2) 当托管提供程序现在只需要一两个 dll 时,我认为这是不值得的。
回答by Wernfried Domscheit
It's a bad idea to copy single DLL's to different directories and hope it will work.
将单个 DLL 复制到不同的目录并希望它能够工作是一个坏主意。
In general ODP.NET provider works only together with corresponding Oracle Client, i.e. in order to use ODP.NET 12 you must also install Oracle Client 12. Same applies for version 11 or 10. Only exception is the ODP.NET Managed Driver, there you need only a single DLL (Oracle.ManagedDataAccess.dll).
通常,ODP.NET 提供程序仅与相应的 Oracle Client 一起使用,即为了使用 ODP.NET 12,您还必须安装 Oracle Client 12。同样适用于版本 11 或 10。唯一的例外是 ODP.NET Managed Driver,有您只需要一个 DLL (Oracle.ManagedDataAccess.dll)。
Furthermore the architecture (32 bit vs. 64 bit) has to match.
此外,架构(32 位与 64 位)必须匹配。
In case you use OLEDB provider it's even not possible to have more than one provider installed (for each architecture) - unless you hack your system by manipulating PATH
variable and Registry all the time.
如果您使用 OLEDB 提供程序,则甚至不可能安装多个提供程序(对于每种架构)——除非您一直通过操纵PATH
变量和注册表来破解您的系统。
My proposal would be: Remove all Oracle Clients from your machine and install only one(or one per architecture) Oracle Client properly. It's very unlikely that an application works with one Oracle Client version only. It is also a good approach to install both 32bit and 64bit on one machine, follow this instruction to do it: Install Oracle x86 and X64 on one machine
我的建议是:从您的机器中删除所有 Oracle 客户端,并仅正确安装一个(或每个架构一个)Oracle 客户端。一个应用程序不太可能只与一个 Oracle Client 版本一起工作。在一台机器上同时安装 32 位和 64 位也是一个不错的方法,请按照以下说明进行操作:在一台机器上安装 Oracle x86 和 X64
In case you really need to test your application with different Oracle Client version, setup a couple of test-PC (maybe in a Virtual-Box) each with a different Client version. Otherwise it will be very challenging to handle it.
如果您确实需要使用不同的 Oracle Client 版本测试您的应用程序,请设置几个测试 PC(可能在 Virtual-Box 中),每个 PC 都具有不同的 Client 版本。否则处理起来会非常困难。
Update:
更新:
I think each (Unmanaged) ODP.NET version works only with according version of Oracle Client. Maybe by chance there are some combinations which work out but in general the versions should match.
我认为每个(非托管)ODP.NET 版本仅适用于相应版本的 Oracle 客户端。也许偶然有一些组合可以解决,但通常版本应该匹配。
I see two different solutions:
我看到两种不同的解决方案:
(1)Ask your client to install his Oracle Client including ODP.NET. He can choose the version, only the architecture (32 bit or 64 bit) has to match. Then you don't supply any ODP.NET with your application.
(1)要求您的客户安装他的 Oracle Client,包括 ODP.NET。他可以选择版本,只有架构(32 位或 64 位)必须匹配。那么您就不会为您的应用程序提供任何 ODP.NET。
In your *.csproj
, resp. *.vbproj
file define your reference like this:
在你的*.csproj
,分别。*.vbproj
文件像这样定义您的参考:
<Reference Include="Oracle.DataAccess">
<SpecificVersion>False</SpecificVersion>
<Private>False</Private>
</Reference>
Attributes like Version=...
or processorArchitecture=...
are not required. Then your application should run with any Oracle/ODP.NET version.
类似Version=...
或processorArchitecture=...
不需要的属性。那么您的应用程序应该可以与任何 Oracle/ODP.NET 版本一起运行。
Your customer can download ODP.NET provider from here: Oracle Data Access Components (ODAC) for Windows Downloadsand install it on top of existing Oracle Client installation. In readme.txt
it says "The files of this zip file is NOT to be installed on top of an existing
Oracle Universal Installer (OUI) based Oracle Home installation.", however I don't see any reason why not doing it. It works well, you just have to carefully provide correct folder for existing Oracle installation and correct ORACLE_HOME
name and do not install dependencies.
您的客户可以从此处下载 ODP.NET 提供程序:适用于 Windows 的 Oracle 数据访问组件 (ODAC) 下载并将其安装在现有 Oracle 客户端安装之上。在readme.txt
它说:“这个zip文件的文件不被基于现有的Oracle通用安装程序(OUI)之上的Oracle Home安装。安装”,但我看不出有任何理由不这样做。它运行良好,您只需要为现有的 Oracle 安装仔细提供正确的文件夹和正确的ORACLE_HOME
名称,并且不要安装依赖项。
(2)In your setup script/exe determine the Version of customer installed Oracle Client and copy according ODP.NET to customer machine.
(2)在您的安装脚本/exe 中确定客户安装的 Oracle 客户端的版本并根据 ODP.NET 复制到客户机器。
In order to determine version of Oracle Client you can to search for file oci.dll
in folders provided by PATH
environment. oci.dll
is a normal .NET assembly, so you can read out the version easily.
为了确定 Oracle Client 的版本,您可以oci.dll
在PATH
环境提供的文件夹中搜索文件。oci.dll
是一个普通的.NET程序集,所以你可以很容易地读出版本。
For a proper installation of ODP.NET follow the file configure.bat
which is part of downloaded ODP.NET XCopy version. In my opinion this batch file is easy to understand.
Basically it does
要正确安装 ODP.NET,请按照configure.bat
下载的 ODP.NET XCopy 版本中的文件进行操作。在我看来,这个批处理文件很容易理解。基本上是这样
1 - Copy file Oracle.DataAccess.dll
to target machine
1 - 将文件复制Oracle.DataAccess.dll
到目标机器
2 - Copy different resource files *\Oracle.DataAccess.resources.dll
to target machen
2 - 将不同的资源文件复制*\Oracle.DataAccess.resources.dll
到目标机器
3 - Add these DLL's to the GAC. This can be done by gacutil.exe
or OraProvCfg.exe
(included in downloader ZIP file) or your setup application provides this operation.
3 - 将这些 DLL 添加到 GAC。这可以通过gacutil.exe
或OraProvCfg.exe
(包含在下载器 ZIP 文件中)或您的安装应用程序提供此操作来完成。
4 - Make a few Regristy entries. Newer ODP.NET versions write/read into HKLM\SOFTWARE\Wow6432Node\Oracle\ODP.NET
(for 32 bit), resp. HKLM\SOFTWARE\Oracle\ODP.NET
(for 64 bit). Older ODP.NET versions use HKLM\SOFTWARE\Oracle\KEY_{ORACLE_HOME_KEY}\ODP.NET\
(for 64 bit), resp HKLM\SOFTWARE\Wow6432Node\Oracle\KEY_{ORACLE_HOME_KEY}\ODP.NET\
(for 32 bit) instead
4 - 制作一些 Regristy 条目。较新的 ODP.NET 版本写入/读取 HKLM\SOFTWARE\Wow6432Node\Oracle\ODP.NET
(对于 32 位),resp。HKLM\SOFTWARE\Oracle\ODP.NET
(对于 64 位)。较旧的 ODP.NET 版本使用HKLM\SOFTWARE\Oracle\KEY_{ORACLE_HOME_KEY}\ODP.NET\
(64 位),resp HKLM\SOFTWARE\Wow6432Node\Oracle\KEY_{ORACLE_HOME_KEY}\ODP.NET\
(32 位)代替
That's it, you should be able to include this in your setup.
就是这样,您应该能够将其包含在您的设置中。