简介ODAC1120320Xcopy_x64是一款面向64位系统的Oracle Data Access Components 11.2.0.3.20版本核心用途是打通SQL Server与Oracle之间的数据通道通过Oracle Provider for OLE DB驱动在SQL Server中创建链接服务器实现跨数据库查询、更新与同步适合需要在异构数据库间做数据集成或运维的开发者。压缩包共194个文件大小54.16MB包含90个dll运行库、42个sql脚本、17个plb存储过程包、可执行文件与bat批处理脚本以及htm说明文档目录覆盖instantclient_11_2、oledb、asp.net等模块便于按需配置部署。已有9183人学习下载资源自带install/configure/uninstall等批处理及readme说明可帮助快速安装、配置和排错适合具备Oracle与SQL Server基础的中高级开发者使用。1. ODAC1120320Xcopy_x64 是什么免安装的 Oracle 数据访问组件解决什么场景把 ODAC1120320Xcopy_x64 拆开看它其实是 Oracle 官方发布的 ODACOracle Data Access Components11.2.0.3.20 的 64 位 Xcopy 发行包。Xcopy 模式意味着这个包不需要跑安装向导解压到目录就能用本质上是 ODP.NETOracle Data Provider for .NET和 OCI Instant Client 的捆绑体。对于在 Windows x64 服务器上部署 .NET 应用、又不想装几百兆 Oracle 客户端的场景这是最省事的方案。我第一次用它是为了一个跑在 Windows Server 2012 R2 上的 ASP.NET 老系统数据库在另一台 Linux 服务器上的 Oracle 11g。服务器权限卡得严DBA 不给装客户端运维只丢过来一个压缩包说解压就能用。当时半信半疑后来花了一个下午把 provider 注册、环境变量、TNS 解析全打通才意识到这套东西的实用价值。适合谁被 Oracle 客户端安装流程恶心过的 .NET 开发者以及需要批量给多台服务器部署数据访问组件的运维。2. 认识 ODAC 11.2.0.3.20 的组件构成ODP.NET、OCI 和 Xcopy 模式的设计逻辑2.1 为什么选 Xcopy 而不是传统安装免安装部署的三个直接好处传统 Oracle 客户端安装包分两类一类是完整的 Oracle Client带 SQL*Plus、Oracle Net Manager、ODBC 驱动等一大堆组件装完占掉 2GB 以上磁盘另一类是 Instant Client只有 OCI 库没有 ODP.NET 托管组件。ODAC Xcopy 恰好站在两者中间——它把 ODP.NET 的 Oracle.DataAccess.dll 和 OCI 层的 oci.dll、oraociei11.dll、tnsnames.ora 解析逻辑打包在一起解压后目录结构就是这个样式ODAC1120320Xcopy_x64/ ├── odp.net/ │ ├── bin/ # Oracle.DataAccess.dll 所在目录 │ │ ├── 2.x/ │ │ └── 4.x/ │ └── ProviderServices/ ├── oci.dll # OCI 客户端核心库 ├── oracore.dll ├── oraociei11.dll # 字符集等基础支持 ├── tnsnames.ora # 可选网络服务名解析 ├── configure.bat # 关键配置脚本 ├── instantclient_11_2/ ├── odp.net20/ └── odp.net4/不做系统级安装带来的好处很实际。第一不写注册表全局项卸载时删目录即可不污染服务器第二同一台机器可以并存多个版本的 ODAC切换时改环境变量就行第三可以把这个目录直接打进发布包配合 CI/CD 流水线实现代码和依赖一起部署。但注意Xcopy 不是完全不碰系统——ODP.NET 要正常工作必须把 provider 注册到 .NET 的 DbProviderFactories 里这一步由 configure.bat 完成后面细说。2.2 解压到运行的最小操作configure.bat 到底做了什么拿到 ODAC1120320Xcopy_x64 压缩包后我习惯把它解压到不带空格的路径比如D:\oracle\odac1120320。带空格的目录不是不能用但后续配环境变量、写批处理脚本时容易踩引号的坑没必要给自己找麻烦。解压完成后最关键的一步是运行 configure.bat命令长这样cd /d D:\oracle\odac1120320 configure.bat D:\oracle\odac1120320 %COMPUTERNAME%configure.bat 需要两个参数第一个是 Oracle Home 路径就是解压目录本身第二个是机器名。%COMPUTERNAME%是 Windows 环境变量在 cmd 里会自动展开为当前主机名。如果机器名包含特殊字符或者想在无人值守脚本里用也可以写死比如configure.bat D:\oracle\odac1120320 WEB-SRV-01。这个脚本做三件事在 machine.config 的 DbProviderFactories 节点下注册 Oracle.DataAccess.Client把安装目录写入注册表的 Oracle 键给当前用户设置 ORACLE_HOME 环境变量。其中最关键的是第一件事因为 .NET 的 DbProviderFactories.GetFactory(Oracle.DataAccess.Client) 是从 machine.config 读取程序集信息的没注册就会报 Unable to find the requested .Net Framework Data Provider。注意configure.bat 必须以管理员身份运行否则对 machine.config 和注册表的写入会被 UAC 拦下来。判断有没有写成功可以直接打开C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config搜 DbProviderFactories 节点看到包含 Oracle.DataAccess.Client 的条目就是成功了。运行完 configure.bat 后还要补两个环境变量。一个是把解压目录加进 PATH让系统找得到 oci.dll另一个是如果有自定义的 tnsnames.ora设置 TNS_ADMIN 指向它所在目录。这些在 2.3 节讲。2.3 部署到目标机器的关键配置环境变量、TNS 解析和权限配置环境变量看起来简单但这里有个容易忽略的细节。ODP.NET 的 DLL 加载机制是Oracle.DataAccess.dll 通过 DllImport 调 oci.dll而 oci.dll 依赖 PATH 才能被找到。如果你只设置了 ORACLE_HOME 而没更新 PATH运行时会报 Ora-12705 或直接说 Cannot locate oci.dll。我用批处理统一处理这三件事在部署脚本里写成这样set ORACLE_HOMED:\oracle\odac1120320 set TNS_ADMIND:\oracle\network\admin set PATH%ORACLE_HOME%;%PATH%TNS_ADMIN 这个变量容易被忽视。ODAC Xcopy 自带的目录里没有像完整客户端那样的 Network\Admin 结构所以默认情况下 ODP.NET 只在当前目录和 ORACLE_HOME 下找 tnsnames.ora。如果项目里维护了一套独立的 tnsnames.ora比如用配置管理工具统一下发就必须通过 TNS_ADMIN 告诉它去哪儿找。设置完之后用tnsping ORCL验证一下网络服务名是否能解析通。不过要注意这个版本自带的是 tnsping.exe放在解压目录里直接用就行。权限问题主要集中在 IIS 场景。ASP.NET 应用程序池的进程账户ApplicationPoolIdentity 或自定义账户需要对该目录有读取和执行权限。最简单的做法是在目录安全设置里给 IIS AppPool池名称 添加读取权限否则会在运行时出现 Access is denied 的错误。这个错误在事件查看器里看到的不是 .NET 异常而是 Windows 的模块加载失败排查时很容易走弯路。3. 用 ODAC Xcopy 跑通第一个 ODP.NET 连接代码、配置与参数细节3.1 最小 C# 连接代码从连接字符串到数据读取配置好环境后验证整套链路是否通的最快方式就是写一段最小代码跑一下。我用 C# 控制台项目演示注意目标平台必须显式设为 x64否则 64 位 ODAC 在 32 位进程里加载会直接抛 BadImageFormatException。代码核心部分如下using System; using Oracle.DataAccess.Client; class Program { static void Main() { // 连接字符串User Id/Password 是数据库账号Data Source 是 TNS 服务名 string connStr User Idscott;Passwordtiger;Data SourceORCL;; using (OracleConnection conn new OracleConnection(connStr)) { conn.Open(); Console.WriteLine(连接成功ServerVersion: conn.ServerVersion); using (OracleCommand cmd new OracleCommand( SELECT EMPNO, ENAME FROM EMP WHERE ROWNUM 5, conn)) using (OracleDataReader reader cmd.ExecuteReader()) { while (reader.Read()) { Console.WriteLine(reader.GetInt32(0) - reader.GetString(1)); } } } } }这段代码里有几个点值得展开。OracleConnection 来自 Oracle.DataAccess.Client 命名空间这是 ODP.NET 非托管驱动如果你的项目是 .NET Core 或 .NET 5需要改用 Oracle.ManagedDataAccess.Core那是另一套程序集本文不展开。连接字符串里的 Data Source 支持三种写法TNS 服务名比如 ORCL需要 tnsnames.ora 配合、EZCONNECT 格式host:port/service_name、以及完整描述符(DESCRIPTION(ADDRESS(PROTOCOLTCP)(HOST192.168.1.10)(PORT1521))(CONNECT_DATA(SERVICE_NAMEorcl)))。在还没有 tnsnames.ora 的早期调试阶段我一般直接上 EZCONNECT少一层解析少一个变量。3.2 关键配置文件machine.config 与 web.config 的 provider 注册ODAC Xcopy 里最让新手困惑的是为什么我引用了 Oracle.DataAccess.dll 还是报错找不到类。原因在于 ODP.NET 不仅是普通的程序集引用它同时是一个 ADO.NET provider必须在 .NET 配置文件的 DbProviderFactories 节点里声明。configure.bat 往 machine.config 写入的内容等效于这段 XMLsystem.data DbProviderFactories add nameOracle Data Provider for .NET invariantOracle.DataAccess.Client descriptionOracle Data Provider for .NET typeOracle.DataAccess.Client.OracleClientFactory, Oracle.DataAccess, Version4.112.3.0, Cultureneutral, PublicKeyToken89b483f429cbfa6a / /DbProviderFactories /system.data这段配置里最严格的是 type 属性的完全限定名PublicKeyToken 必须和实际程序集一致版本号也不能乱写。如果你的项目直接 new OracleConnection不经过 ProviderFactories.GetFactory那这段配置可以不要但如果你用了 Entity Framework 6 或 DbProviderFactories.GetFactory 这类抽象层注册就是硬性要求。在一台机器上装了多个版本 ODAC 导致配置混乱时我一般会手动编辑 machine.config 来做版本对齐比反复跑 configure.bat 更快。对于 Web 应用还可以把 provider 注册写在应用程序自己的 web.config 里这样不会影响服务器上的其他站点。做法是复制上面那段 XML 到 web.config 的system.data节点下并把程序集版本改成你实际引用的版本。这个方式在共享主机环境里尤其实用不需要管理员权限。3.3 连接字符串参数和 Oracle 版本匹配3 个必调项连接字符串的默认参数对大多数场景够用但生产环境里我至少会调三个东西。第一个是 PoolingODP.NET 默认开启连接池值为 true。连接池可以有效降低频繁 Open/Close 的开销但在数据库重启或网络闪断后池里的连接可能已经失效需要设置Connection Lifetime或Validate Connectiontrue来自动清理。第二个是Statement Cache Size默认 0关闭如果应用的 SQL 重复度高像 ERP 系统里几百个并发同时执行同类查询调到 20 左右能明显降低服务器端硬解析的压力。第三个是Self Tuning这个参数在 11.2 里默认开启会自动调整连接池和语句缓存的内部行为。听起来很智能但在某些老库上反而会掩盖问题。我遇到过的情况是自调优把语句缓存撑到很大内存吃紧后整个应用变慢关掉 Self Tuning 后表现反而稳定。注意这个参数在连接字符串里写成Self Tuningfalse只在 ODP.NET 4.112 以上版本支持。连接字符串示例User Idscott;Passwordtiger;Data Source192.168.1.10:1521/orcl; Poolingtrue;Connection Lifetime30;Statement Cache Size20;Self Tuningfalse;所有参数都不是拍脑袋乱加的调之前先去数据库侧看会话数和等待事件。加了连接池后数据库的会话数会明显比应用线程数少这是预期内的事别把它当异常去排查。4. 部署与调用中的常见坑ODAC1120320Xcopy_x64 避坑记录4.1 坑 1System.Data.OracleClient 与 ODP.NET 混淆编译过了但运行报错现象项目引用了 System.Data.OracleClient微软内置的旧驱动代码写了using System.Data.OracleClient;编译能通过部署到服务器后运行时报 ORA-06401 或 Oracle client could not be loaded。原因微软的 System.Data.OracleClient 是 .NET Framework 内置的它走的是老版 OCI 调用链对 Oracle 11.2 的某些特性支持不完整而且微软官方早已标记过时ODAC Xcopy 的这个包里根本不含它所需的适配层。更隐蔽的是某些老的第三方库内部用了这个命名空间表面上看不出来。解决全局搜索System.Data.OracleClient引用全部替换为Oracle.DataAccess.Client。操作分两步从项目引用里移除 System.Data.OracleClient再添加对解压目录下 odp.net\bin\4.x\Oracle.DataAccess.dll 的引用。改完后把代码里的System.Data.OracleClient.OracleConnection统一换成Oracle.DataAccess.Client.OracleConnection。如果第三方库改不了最省事的办法是升级那个库或者用 ODP.NET 的托管版重写数据访问层。4.2 坑 2x64 进程加载 32 位 ODACBadImageFormatException 追到入口现象应用启动时报System.BadImageFormatException: 试图加载格式不正确的程序集错误 HRESULT 0x8007000B堆栈指向 Oracle.DataAccess.dll 或 oci.dll。原因最常见的是进程是 32 位的。IIS 应用程序池默认启用 32 位应用程序为 False但如果你是手动建的池子很容易把它改成 True另外 Visual Studio 里项目平台目标如果是 x86本地调试时也会复现。我排过最离谱的一个案例是部署包里同时带了一个 32 位的 Oracle.DataAccess.dll把 x64 目录里的覆盖了进程加载时先找到受管程序集再去找 oci.dll两个位数不一致就崩了。解决先确认进程位数任务管理器里看到进程名带*32后缀就是 32 位。IIS 里把应用程序池的高级设置启用 32 位应用程序改为 False独立程序则把平台目标改为 x64。然后检查服务器上where oci.dll的输出确认 PATH 里排在第一位的 oci.dll 是 ODAC1120320Xcopy_x64 解压目录下的删除或改名掉任何混进来的 x86 版本。这事用批处理在部署时做掉免得每台机器都手动查一遍。4.3 坑 3TNS 解析失败ORA-12154 但同为 x64 的另一台机器正常现象两个配置几乎一模一样的服务器A 机器连接正常B 机器报ORA-12154: TNS:could not resolve the connect identifier specified。对比了连接字符串、tnsnames.ora 内容完全一致。原因ORA-12154 的本质是 ODP.NET 在指定的位置找不到 tnsnames.ora或者文件里有语法错误。A 和 B 的差异在于 TNS_ADMIN 环境变量有没有真正生效。我在排查时发现B 机器上 TNS_ADMIN 在用户变量里设置了但 IIS 应用程序池进程的账户是系统账户读不到用户变量等于没设置。解决把 TNS_ADMIN 从用户变量挪到系统变量修改后重启 IIS 应用程序池iisreset 最省事。为了彻底摆脱对文件的依赖我后续在新项目里直接改用 EZCONNECT 格式的 Data Source比如192.168.10.15:1521/orcl完全不经过 tnsnames.ora 解析。这样部署时少传一个文件、少踩一个坑代价是放弃 RAC 负载均衡里通过服务名切换的功能对单实例数据库来说完全够用。4.4 坑 4OCI 版本与数据库服务器不匹配ORA-03134 或连接建立后即断开现象ODAC 11.2 连 Oracle 11.2 的库没问题但连 Oracle 19c 或更高版本数据库时报ORA-03134: Connections to this server version are no longer supported或者连接成功但执行任何 SQL 都会触发 ORA-03113。原因Oracle 的服务端在 18c 之后对老版本客户端做了限制11.2 的 OCI 不再被支持。这是硬性兼容性边界不是配置能解决的。反过来如果你用太新的 ODP.NET 连老库比如 8i同样有成堆的兼容性问题。解决确认两端版本的交叉兼容矩阵。通常我会直接换新版本的 ODAC比如 ODAC 19c 的 Xcopy 包它带的 OCI 支持连 11.2 到 19c 的数据库。如果数据库版本确实太老如 9i/10g反而要保留 11.2 这个版本的 ODAC此时不需要升级维持现状即可。判断依据很简单查看数据库的 PRODUCT_COMPONENT_VERSION和客户端的 oci.dll 版本做对照虽然官方有兼容表但我更建议直接做冒烟测试而不是查文档。4.5 坑 5configure.bat 报错或 machine.config 被写坏连锁引发其他应用异常现象跑 configure.bat 时提示成功但打开 machine.config 发现 DbProviderFactories 节点重复出现了多条 Oracle 记录版本号还不一致或者运行其他 .NET 应用时报Unrecognized configuration section system.data。原因我之前在同一台机器上先后跑过不同版本 ODAC 的 configure.bat它不会清理旧记录只会追加。多条 invariant 相同的记录会导致运行时只认第一条它的版本和你实际引用的版本一旦不一致就报找不到程序集。另一种情况是手动编辑 machine.config 时标记写错破坏了 XML 结构整个 .NET Framework 上的应用全挂。解决原则是能不入库就不入库。我现在的做法是不在 machine.config 上折腾而是把 provider 注册写进项目自己的配置文件里。独立的控制台程序用 app.configWeb 应用用 web.config只对当前应用生效不做全局变更。如果 machine.config 已经被写花先备份再用原始文件覆盖回去或者用 NuGet 包里的 install 脚本来做解析。总之Xcopy 模式的价值就在于低侵入别用出一个高侵入的结果。5. 进阶玩法把 ODAC1120320Xcopy_x64 做成可复用的绿色部署包在跑过几十台服务器的部署之后我总结了一套比手动操作更稳的流程核心是把 ODAC 目录加进安装包配合一个环境检查脚本自动验证。目录结构做成这样deploy_pkg/ ├── odac1120320x64/ # 解压后的 ODAC 目录 ├── tnsnames.ora # 统一维护的 TNS 配置 ├── setup_env.bat # 环境变量 权限设置 └── verify_conn.exe # 冒烟测试工具setup_env.bat 里做的事包括设置系统级 ORACLE_HOME 和 TNS_ADMIN、把 ODAC 目录插入 PATH 最前面、调用 configure.bat 但把参数写死为当前机器名。因为 ODAC 解压后配置过程涉及 machine.config这在 CI/CD 里没法完全自动化我一般不会把它做成流水线的常规步骤而是做成首次装机的一次性脚本。验证环节我强烈建议写一个最小的连接工具不要依赖大型业务代码。工具输入参数是连接字符串启动后依次做三件事确认 Oracle.DataAccess.dll 版本、尝试建立连接、执行SELECT 1 FROM DUAL。只要这步通过部署目标机器的环境就基本可信了。否则排查方向要么是进程位数不对、要么是配置文件和 tnsnames 没生效再往下看 Windows 事件日志里的模块加载错误。这个思路帮我省过不少半夜被叫起来排障的时间。我的习惯是任何一台机器部署完都把tnsping输出、PowerShell 里执行[System.Reflection.AssemblyName]::GetAssemblyName(...Oracle.DataAccess.dll).Version的结果存档一份后续升级或者排障时对比用。配置类的坑十有八九是版本不一致和环境变量不到位文档存得越细返工越少。希望帮到你。本文还有配套的精品资源点击获取
