ODP.NET托管库做解析别名,但32位的库做 [英] ODP.NET Managed library does resolve alias, but 32-bit library does

查看:183
本文介绍了ODP.NET托管库做解析别名,但32位的库做的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我的盒子安装32位驱动程序(它们被安装和一些数据库管理员配置)

I have 32-bit drivers installed on my box (they were installed and configured by some DBAs)

我写了一个简单的脚本来测试驱动,几乎如下:

I wrote a simple script to test the drivers which pretty much is as follows

using (DataTable table = new DataTable())
{
    using (OracleConnection connection = new OracleConnection())
    {
        connection.ConnectionString = "Data Source=alias;User id=user;Password=password";
        connection.Open();
        using (OracleCommand command = connection.CreateCommand())
        {
            command.CommandType = CommandType.Text;
            command.CommandText = "SELECT * FROM DUAL";
            table.Load(command.ExecuteReader());
        }
    }
}

当我编译这个应用程序32位与32位Oracle.DataAccess.dll,它执行顺利。

When I compile this application as 32-bit with the 32-bit Oracle.DataAccess.dll, it executes without a hitch.

但是,如果我编译应用程序与Oracle.ManagedDataAccess.dll值为anycpu ,我得到一个ORA-12154(无法解析指定的连接标识符)错误。

However if I compile the application as AnyCPU with the Oracle.ManagedDataAccess.dll, i get an ORA-12154 (could not resolve the connect identifier specified) error.

如果我用tnsping别名,它工作正常,并告诉我的连接标识符与现实数据库名。

If I tnsping alias, it works correctly and tells me the connect identifier with the real database name.

如果我再改为使用真实的数据库名称,而不是别名,然后尝试再次与管理库的连接字符串,它执行顺利

If I then change the connection string to use the real database name instead of the alias, and then try with the managed library again, it executes without a hitch.

我一直在阅读了一圈,发现答案它说,管理驱动依赖于tnsnames.ora文件来解析别名,但我靠在SQLNET.ORA和ldap.ora定义的LDAP服务器上。

I've been reading around and found this answer which says the managed driver relies on the tnsnames.ora file to resolve the aliases, however I rely on LDAP servers defined in sqlnet.ora and ldap.ora.

当我TNSPING,它说,它使用SQLNET.ORA解析名称。

When I tnsping, it says it uses sqlnet.ora to resolve the name.

那为什么托管驱动程序不工作?

So how come the managed drivers do not work?

推荐答案

愿这解决方法是适合你的。你可以通过自己查询LDAP服务器,并把完整的连接字符串代码

May this workaround is suitable for you. You can query the LDAP server by your own and put the full connection string to your code.

您可以解决从LDAP使用此代码的连接字符串:

You can resolve the connection string from LDAP with this code:

using (OracleConnection connection = new OracleConnection())
{
    connection.ConnectionString = "Data Source=" + ResolveServiceNameLdap("alias") + ";User id=user;Password=password";
    connection.Open();
}



...

...

  private static string ResolveServiceNameLdap(string serviceName)
  {
     string tnsAdminPath = Path.Combine(@"C:\oracle\network", "ldap.ora");
     // or something more advanced...

     // ldap.ora can contain many LDAP servers
     IEnumerable<string> directoryServers = null;

     if ( File.Exists(tnsAdminPath) ) {
        string defaultAdminContext = string.Empty;

        using ( var sr = File.OpenText(tnsAdminPath) ) {
           string line;

           while ( ( line = sr.ReadLine() ) != null ) {
              // Ignore comments or empty lines
              if ( line.StartsWith("#") || line == string.Empty )
                 continue;

              // If line starts with DEFAULT_ADMIN_CONTEXT then get its value
              if ( line.StartsWith("DEFAULT_ADMIN_CONTEXT") )
                 defaultAdminContext = line.Substring(line.IndexOf('=') + 1).Trim(new[] { '\"', ' ' });

              // If line starts with DIRECTORY_SERVERS then get its value
              if ( line.StartsWith("DIRECTORY_SERVERS") ) {
                 string[] serversPorts = line.Substring(line.IndexOf('=') + 1).Trim(new[] { '(', ')', ' ' }).Split(',');
                 directoryServers = serversPorts.SelectMany(x => {
                    // If the server includes multiple port numbers, this needs to be handled
                    string[] serverPorts = x.Split(':');
                    if ( serverPorts.Count() > 1 )
                       return serverPorts.Skip(1).Select(y => string.Format("{0}:{1}", serverPorts.First(), y));

                    return new[] { x };
                 });
              }
           }
        }

        // Iterate through each LDAP server, and try to connect
        foreach ( string directoryServer in directoryServers ) {
           // Try to connect to LDAP server with using default admin contact
           try {
              var directoryEntry = new DirectoryEntry("LDAP://" + directoryServer + "/" + defaultAdminContext, null, null, AuthenticationTypes.Anonymous);
              var directorySearcher = new DirectorySearcher(directoryEntry, "(&(objectclass=orclNetService)(cn=" + serviceName + "))", new[] { "orclnetdescstring" }, SearchScope.Subtree);
              SearchResult searchResult = directorySearcher.FindOne();
              var value = searchResult.Properties["orclnetdescstring"][0] as byte[];
              if ( value != null )
                 connectionString = Encoding.Default.GetString(value);

              // If the connection was successful, then not necessary to try other LDAP servers
              break;
           } catch {
              // If the connection to LDAP server not successful, try to connect to the next LDAP server
              continue;
           }
        }

        // If casting was not successful, or not found any TNS value, then result is an error 
        if ( string.IsNullOrEmpty(connectionString) ) 
           throw new Exception("TNS value not found in LDAP");

     } else {
        // If ldap.ora doesn't exist, then throw error 
        throw new FileNotFoundException("ldap.ora not found");
     }

     return connectionString;
  }

这篇关于ODP.NET托管库做解析别名,但32位的库做的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆