我们的应用程序使用托管的ODP.NET代码来调用各种Oracle过程。
对于我们的一个客户,他们正在使用公共数据库链接,并在过程中引用链接表中的链接表正在失败。在进行进一步测试后,任何试图通过odp.net进行查询的任何尝试都会失败。
ORA-12154:TNS:无法解析指定的连接标识符
完整堆栈:
Oracle.ManagedDataAccess.Client.OracleException: ORA-12154: TNS:could not resolve the connect identifier specified
at OracleInternal.ServiceObjects.OracleCommandImpl.VerifyExecution(OracleConnectionImpl connectionImpl, Int32& cursorId, Boolean bThrowArrayBindRelatedErrors, OracleException& exceptionForArrayBindDML, Boolean& hasMoreRowsInDB, Boolean bFirstIterationDone)
at OracleInternal.ServiceObjects.OracleCommandImpl.ExecuteReader(String commandText, OracleParameterCollection paramColl, CommandType commandType, OracleConnectionImpl connectionImpl, OracleDataReaderImpl& rdrImpl, Int32 longFetchSize, Int64 clientInitialLOBFS, OracleDependencyImpl orclDependencyImpl, Int64[] scnForExecution, Int64[]& scnFromExecution, OracleParameterCollection& bindByPositionParamColl, Boolean& bBindParamPresent, Int64& internalInitialLOBFS, OracleException& exceptionForArrayBindDML, Boolean isDescribeOnly, Boolean isFromEF)
at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteReader(Boolean requery, Boolean fillRequest, CommandBehavior behavior) at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader()
at [APPLICATION CODE]
这很奇怪,因为即使在客户端计算机上没有没有TNS名称ora文件。
我们的应用程序甚至不使用TNS名称,它使用明确的连接字符串详细信息。
我们甚至通过Devart Oracle驱动程序运行测试查询,并且他们也成功了。
好像是专门通过托管odp.net进行呼叫使服务器对数据库链接的处理方式不同。
ODP.NET Query (Client Machine A) > (Server A) > Table (Server B) = ERROR
SQL Plus Query (Client Machine A) > (Server A) > Table (Server B) = SUCCESS
DEV ART Query (Client Machine A) > (Server A) > Table (Server B) = SUCCESS
我们现在正在使用的测试查询是一个简单的选择语句
有人知道我们如何像SQL Plus一样将ODP.NET推迟到服务器以获取此信息?
db链接信息:
OWNER: PUBLIC
USERNAME: [FIXED OTHER USER]
这无疑是服务器A和服务器之间的连接(数据库链接)的问题。
在tnsnames.ora
文件中,服务器B中的TNS名称可能丢失了服务器A或服务器A在其数据库链接中具有错误的TNS名称。
如果这是客户端问题,我可以想象会收到ORA-12154错误,但不是ORA-04088:显然,如果您可以进入触发器,那么您与服务器A的连接还可以。
我要说的是,下一步将是直接连接到服务器A上的数据库,并尝试通过数据库链接在服务器B上的数据库中查询一个表。我希望这会因相同的ORA-12154错误而失败。
从您的描述中,可能是:
- 这是您的ODP.NET客户端的配置问题。
- 此外,客户端可能首先无法连接到服务器A,更不用说服务器b。
ODP.NET是一个薄的客户端(不涉及本机代码)的事实,应排除与Oracle客户端二进制文件相关的任何配置:驱动程序是"自我包含"的,并且完全独立于您的SQLPLUS安装。我的意思是,例如,如果计算机的%路径%变量存在错误,它会影响数据的配置,而不是所涉及的二进制文件。
可能是ODP.NET可能看不到适当的ORACLE_HOME
变量(例如C:u01appclientproduct12.1.0client_1
)。而且可能,配置错误在ODP.NET无法获取TNS名称文件的位置中表现出来。
我建议:
- 尝试查看是否有另一个客户出现在您的路径中,并隐藏您的预期目录。例如:
C:u01appclientproduct11.2.1client_1bin;C:u01appclientproduct12.1.0client_1bin
。在这种情况下,作为快速尝试,请将您的ODP.NET客户端放在首位。这很可能会使您的ODP.NET代码拾取指向正确的Oracle_home的指针,并且将随后进行TNS配置。对于复杂的设置,请考虑Oracle将不同的ORACLE_HOME
值存储在注册表中,并为您提供其他方式以外的位置,以选择所需的位置。如果有兴趣,请参见使用多个Oracle Homes。当然,不要忘记将您的TNS名称放在正确的位置,该TNS应该指向服务器A,而不是服务器b。 - 另外,尝试创建一个可见的Windows帐户可见的其他环境变量,该变量正在执行ODP.NET代码;该变量应称为
TNS_ADMIN
,并指向Oracle客户端的管理目录(类似于..product12.1.0client_1networkadmin
)。确保您的ODP.NET通过从ODP.NET客户端发出string tns_admin = Environment.GetEnvironmentVariable("TNS_ADMIN")
来看到它。 - 如果以上不起作用,请尝试完全避免使用TNS的内容,以这样的连接字符串中指定所有信息:
<connectionStrings>
<add name="Server_A" connectionString="SERVER=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=MyHost)(PORT=MyPort))(CONNECT_DATA=(SERVICE_NAME=MyOracleSID)));
uid=myUsername;pwd=myPassword;" />
</connectionStrings>
后一个设置在此处显示或此处略有不同的替代方案。
我认为,将TNS信息嵌入您的ODP.NET配置实际上比依赖主机OS配置的任何其他解决方案都要干净,因为使您的ODP.NET真正便携ODP.NET配置,而不是主机变量)。有关如何关联TNS和ODP.NET配置的更多示例Vijay的博客。
最后,SQLPlus正在工作并不令人惊讶,因为它可能看到不同的环境变量以获取连接标识符或ORACLE_HOME
。
完全没有tnsnames.ora文件的事实可能表明
- 运行的任何一个sqlpus都在命令行上指定连接,例如
sqlplus user/password@(description=(address_list=(address=.......ODS)))
(请参阅TOM"如何在没有TNSNAMES.ora的情况下连接sqlplus") - 或Oracle实例位于同一服务器上,因此严格不需要侦听器,您可以跳过TNS配置(请参阅需要侦听器的连接)
我们的客户端能够在服务器端解决此问题。问题是DB链接的格式。
原始DB链接:
CREATE PUBLIC DATABASE LINK [LINK_NAME]
CONNECT TO [USER]
IDENTIFIED BY [PASSWORD]
USING [TNS_NAME]
显然在ODP.NET上,TNS名称参考不足。客户端切换到完整的连接细节后,就解决了问题。
更新的DB链接:
CREATE PUBLIC DATABASE LINK [LINK_NAME]
CONNECT TO [USER]
IDENTIFIED BY [PASSWORD]
USING
'(DESCRIPTION =
(SDU=[SDU])
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = [HOSTNAME])(PORT = [PORT]))
(CONNECT_DATA = (SID=[SID])
)'
更多详细信息:
https://docs.oracle.com/cd/b19306_01/server.102/b14200/statements_5005.htm