为啥 Oracle.ManagedDataAccess 不工作而 Oracle.DataAccess 工作?

Posted

技术标签:

【中文标题】为啥 Oracle.ManagedDataAccess 不工作而 Oracle.DataAccess 工作?【英文标题】:Why would Oracle.ManagedDataAccess not work when Oracle.DataAccess does?为什么 Oracle.ManagedDataAccess 不工作而 Oracle.DataAccess 工作? 【发布时间】:2013-07-01 14:48:50 【问题描述】:

我正在开发一个非常简单的应用程序,我打算用它来解决我在几台机器上遇到的问题,但在我还没走到那一步之前,我遇到了一些问题,包括 cpu 架构差异和 Oracle 数据库库。

我有一个列在tnsnames.ora 中的数据库服务器,它位于我的C:\oracle\11g\network\admin 目录中。如果我 tnsping 此服务器,我会得到所需的响应。如果我使用 Oracle.DataAccess.Client 编写我的 C# 程序以使用以下代码连接到该服务器,它就可以工作。

string connectionString = "Data Source=DSDSDS;User Id=UNUNUN;Password=PWPWPW;";
DataTable dataTable = new DataTable();

using (var connection = new OracleConnection(connectionString)) 
    connection.Open();
    using (var command = new OracleCommand()) 
        command.Connection = connection;
        command.CommandText = sql;
        command.CommandType = CommandType.Text;
        using (var oda = new OracleDataAdapter(command)) 
            oda.Fill(dataTable);
        
    

但是,Oracle.DataAccess 取决于运行它的系统的体系结构。我看到还有另一个库 Oracle.ManagedDataAccess 是架构独立的。当我使用这个库时,它不再能够连接到服务器。一个ORA-12545: Network Transport: Unable to resolve connect hostname 被抛出。

为什么会这样?这两个库之间有什么不同,因为根据我目前所读到的内容,这应该不是问题。

额外信息:

%ORACLE_HOME% 和 %TNS_ADMIN% 未定义(请记住 tnsping 和 Oracle.DataAccess 有效) PATH 定义了C:\oracle\11g\BIN。 我的机器只有一个tnsnames.ora文件

如果我将 tnsnames.ora 移动到与我的 .exe 文件相同的位置,它就可以工作。为什么Oracle.DataAccess 可以在C:\oracle\11g\network\admin 目录下找到tnsnames.ora 而Oracle.ManagedAccess 却找不到?

【问题讨论】:

我实际上遇到了同样的问题,不管 app.config 中的 TNS_ADMIN 设置如何。 你解决了吗?你能解释一下吗? 【参考方案1】:

在 ODP.NET、Managed Driver 中解析 TNS 名称的优先顺序是这样的(参见here):

    .NET 配置文件中“dataSources”部分中的数据源别名。 tnsnames.ora 文件中的数据源别名,位于 .NET 配置文件中“TNS_ADMIN”指定的位置。 tnsnames.ora 文件中的数据源别名与 .exe 位于同一目录中。 tnsnames.ora 文件中的数据源别名存在于 %TNS_ADMIN%(其中 %TNS_ADMIN% 是环境变量设置)。 %ORACLE_HOME%\network\admin 中的 tnsnames.ora 文件中的数据源别名(其中 %ORACLE_HOME% 是环境变量设置)。

我相信您的示例适用于 Oracle.DataAccess 但不适用于 Oracle.ManagedDataAccess 的原因是后者不支持基于 Windows 注册表的配置(请参阅documentation) - ODP.NET 安装设置了 ORACLE_HOME 注册表项( HLKM\SOFTWARE\Oracle\Key_NAME\ORACLE_HOME),只有非托管部分才能识别。

【讨论】:

好吧,这确实让空气稍微好一些。但是我的最新问题是“无法识别的配置部分 oracle.manageddataaccess.client”。看起来也需要“
【参考方案2】:

尝试将 tnsnames.ora 的路径添加到配置文件中:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <oracle.manageddataaccess.client>
    <version number="4.112.3.60">
      <settings>
        <setting name="TNS_ADMIN" value="C:\oracle\product\10.2.0\client_1\NETWORK\ADMIN\" />
      </settings>
    </version>
  </oracle.manageddataaccess.client>
</configuration>

【讨论】:

如果 TNS_ADMIN 的值正确,那么问题可能出在版本号上。尝试使用 我正在这样做。如果有人以编程方式可以看到 tnsnames 和 sqlnet 都在使用中,那就太好了;)我正在使用几天前发布的生产版本 121.1.0。但无论如何谢谢! :) 我试了一下,但没有成功。我根据我的设置将路径更改为 C:\oracle\11g\network\admin\,但我收到:Oracle.ManagedDataAccess.dll System.TypeInitializationException 中出现“System.TypeInitializationException”类型的第一次机会异常:类型初始化程序对于 'OracleInternal.Common.ProviderConfig' 抛出异常。 ---> System.Configuration.ConfigurationErrorsException:配置系统初始化失败---> System.Configuration.ConfigurationErrorsException:无法识别的配置部分oracle.manageddataaccess.client。 上面的设置终于解决了我在安装新的Oracle客户端后在c#项目中的问题。谢谢。 我认为这是 app.config?关于如何改变它与测试环境的任何建议?【参考方案3】:

为了避免不知道在哪里寻找 TNSNAMES.ORA 的所有 Oracle 混乱(我有多个 Oracle 版本和 32/64 位的额外混淆),您可以将现有 TNSNAMES.ORA 中的设置复制到您自己的配置文件并将其用于您的连接。 假设您对 TNSNAMES.ORA 中的“DSDSDS”引用感到满意,它映射到以下内容:

DSDSDS=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(Host=DSDSDSHost)(Port=4521)))(CONNECT_DATA=(SERVICE_NAME=DSDSDSService)))
您可以在第一个“=”之后获取文本,并在使用“DSDSDS”的任何地方使用它,并且无需查找 TNSNAMES.ORA 即可知道如何连接。 现在您的连接字符串将如下所示: string connectionString = "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(Host=DSDSDSHost)(Port=4521)))(CONNECT_DATA=(SERVICE_NAME=DSDSDSService)));User Id=UNUNUN;Password=PWPWPW;";

【讨论】:

我应该将 Connection Timeout 参数放在那个长长的 munster 中的什么位置? 所有允许的属性都用分号分隔。数据源属性使它看起来像堂兄它! Oracle 文档有完整的属性列表(包括连接超时,您可以在双引号内的最后一个分号后添加):docs.oracle.com/cd/B13789_01/win.101/b10117/features001.htm .Net 5 应用程序最简单的工作解决方案!【参考方案4】:

一旦我在连接字符串中找到了它要查找的格式,它就可以像 Oracle.ManagedDataAccess 一样正常工作。无需单独处理任何事情。

DATA SOURCE=DSDSDS:1521/ORCL;

【讨论】:

【参考方案5】:

我遇到了类似的问题......为了解决这个问题,我所做的是卸载 ODP。 NET 并重新安装在与 oracle 服务器相同的目录中......使用服务器选项您会注意到大多数产品已经安装(在安装 12c 数据库时)因此只需选择其他功能并最终完成安装。 ...

请注意,只有当您在同一台机器(即您的笔记本电脑)上安装了 12c 时,此解决方法才有效............

如果您的数据库位于笔记本电脑以外的服务器计算机上,请选择客户端选项而不是服务器,然后在您的 app.config 中包含 TNS_ADMIN 并且不要忘记指定版本...

因为我的安装是在我的笔记本电脑上,所以我的 App.config 如下:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
    </startup>
</configuration>


 /////////the below code is a sample from oracle company////////////////


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Oracle.ManagedDataAccess.Client;

///copy these lines in a button click event 
    string constr = "User Id=system; Password=manager; Data Source=orcl;";
// Click here and then press F9 to insert a breakpoint
        DbProviderFactory factory =
    DbProviderFactories.GetFactory("Oracle.ManagedDataAccess.Client");
            using (DbConnection conn = factory.CreateConnection())
            
                conn.ConnectionString = constr;
                try
                
                    conn.Open();
                    OracleCommand cmd = (OracleCommand)factory.CreateCommand();
                    cmd.Connection = (OracleConnection)conn;

//to gain access to ROWIDs of the table
//cmd.AddRowid = true;
                    cmd.CommandText = "select * from all_users";

                    OracleDataReader reader = cmd.ExecuteReader();

                    int visFC = reader.VisibleFieldCount; //Results in 2
                    int hidFC = reader.HiddenFieldCount;  // Results in 1

                    MessageBox.Show(" Visible field count: " + visFC);

                    MessageBox.Show(" Hidden field count: " + hidFC);


                    reader.Dispose();
                    cmd.Dispose();
                
                catch (Exception ex)
                
                    MessageBox.Show(ex.Message);
                      MessageBox.Show(ex.StackTrace);
                
            

【讨论】:

我希望配置具有您在答案中引用的节点?【参考方案6】:

就我而言,上面所说的一切都很好,但我仍然收到ORA-12545: Network Transport: Unable to resolve connect hostname

我尝试 ping Oracle 机器并发现我看不到它并将其添加到主机文件中。然后我收到另一条错误消息ORA-12541: TNS:no listener。经过调查,我意识到从不同的机器上 ping 相同的主机名得到不同的 IP 地址(我不知道为什么),我更改了主机文件中的 IP 地址,100% 解决了问题。

我很费心写我的经验,因为它看起来很明显,但是虽然我确定问题出在上述设置中,但我完全忘记检查我是否真的可以看到远程数据库机器。当你不知道发生了什么事情时,请记住......

这些链接对我帮助很大:

http://www.moreajays.com/2013/03/ora-12545-connect-failed-because-target.html http://www.orafaq.com/wiki/ORA-12541

【讨论】:

【参考方案7】:

晚会“有点”迟到,但真正的答案是 - 如果您使用 Oracle.ManagedDataAccess ODP.NET 提供程序,您应该忘记 network\adminOracle clientOracle_Home 等内容。

这是你需要的

    下载并安装 Oracle Developer Tools for VSODAC。注意 - 开发工具将为您安装 ODAC。这将在C:\Program Files (x86) 下创建相对较小的安装。拥有完整的开发工具,小于 60Mb 在您的项目中,您将安装带有相应版本的 ODP.net (Oracle.ManagedDataAccess.dll) 的 Nuget 包,您将参考这些包

    此时您有 2 个连接选项。

    a) 在连接字符串中设置datasource,格式如下

    DataSource=ServerName:Port/SID . . .DataSource=IP:Port/SID . . .

    b) 创建tnsnames.ora 文件(只是它与以前的经验不同)。有条目:

    AAA = (描述 = (地址 = (协议 = TCP)(主机 = 服务器名或 IP)(端口 = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = SIDNAME)))

    然后将此文件放入运行应用程序的 bin 文件夹中。 现在您可以使用您的连接名称进行连接 - DataSource=AAA . . . 因此,即使您有 tnsnames.ora,但使用 ODP.net managed 它的工作方式有点不同 - 您创建本地TNS 文件。现在,很容易管理它。

总而言之 - 使用 托管,无需繁重的 Oracle 客户端、Oracle_home 或了解 Oracle 安装文件夹的深度。一切都可以在您的 .net 应用程序结构中完成。

【讨论】:

【参考方案8】:

我收到了同样的错误信息。为了解决这个问题,我只是用旧的Oracle.DataAccess 程序集替换了Oracle.ManagedDataAccess 程序集。如果您需要在新装配中找到新功能,此解决方案可能不起作用。就我而言,我有更多优先级更高的问题,然后尝试配置新的 Oracle 程序集。

【讨论】:

以上是关于为啥 Oracle.ManagedDataAccess 不工作而 Oracle.DataAccess 工作?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?

为啥需要softmax函数?为啥不简单归一化?

为啥 g++ 需要 libstdc++.a?为啥不是默认值?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?

为啥 CAP 定理中的 RDBMS 分区不能容忍,为啥它可用?