SQLGetInfo - 如何使用此函数
SQLGetInfo - How to use this function
我开发了一个 c# 应用程序,它连接到许多类型的数据库服务器,如 Sql、Oracle、Mysql 等。连接是使用 ODBC[=29= 建立的].
我需要找到建立连接的服务器类型(DBMS 类型),因为用户只输入 DSN 名称。
经过几个小时的冲浪,我发现我的需求只能通过这个函数实现SQLGetInfo。但是我不知道如何在C#中处理这个问题。
甚至已经检查过这个Link1。
从上面link,我发现ODBC API只给出了DataBase name and DataSource Name。但是我需要找到Datatbase类型,比如它是SQL连接还是Oracle 连接或我的SqlConnection.
是否可以从 DSN 名称获取 DBMS 类型..?
注意:我不想从注册表中读取它 setting.I 尝试了这个并且它有效,但是我遇到了权限问题..!
您是否尝试解析 OdbcConnection 的 .Driver 属性?
它将向您显示连接使用的数据库包装器驱动程序。
您也可以在 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ODBC
的注册表中找到这些映射
有时它只是一个 .dll 名称(例如,对于 Microsoft Excel 驱动程序),但它可以给你一个提示。
您还可以执行数据库特定命令以从服务器获取数据库版本,如下所示:
static void Main(string[] args)
{
var cn = new OdbcConnection("DSN=mysql1");
Console.WriteLine("DBType: {0}", GetDbType(cn));
Console.Read();
}
public enum DbType
{
UNSUPPORTED = 0,
MYSQL = 1,
ORACLE = 2,
MSSQL = 3,
POSTGRESQL = 4,
JET = 5
}
public static DbType GetDbType(OdbcConnection cn)
{
DbType t = DbType.UNSUPPORTED;
try
{
if (cn.State != ConnectionState.Open) cn.Open();
if (cn.Driver == "odbcjt32.dll")
{
return DbType.JET;
}
var cmd = cn.CreateCommand();
string outstring = "";
cmd.CommandText = "SELECT * FROM v$version";
try
{
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
outstring = String.Format("{0}", reader.GetString(0));
}
}
catch (Exception)
{
cmd = cn.CreateCommand();
cmd.CommandText = "SELECT @@version, @@version_comment FROM dual";
try
{
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
outstring = String.Format("{0} {1}", reader.GetString(0), reader.GetString(1));
}
}
catch (Exception)
{
cmd = cn.CreateCommand();
cmd.CommandText = "SELECT @@version";
try
{
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
outstring = String.Format("{0}", reader.GetString(0));
}
}
catch (Exception)
{
cmd = cn.CreateCommand();
cmd.CommandText = "SELECT version()";
try
{
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
outstring = String.Format("{0}", reader.GetString(0));
}
}
catch (Exception)
{
}
}
}
}
outstring = outstring.ToUpper();
if (outstring.Contains("MYSQL"))
{
t = DbType.MYSQL;
}
else if (outstring.Contains("ORACLE"))
{
t = DbType.ORACLE;
}
else if (outstring.Contains("SQL SERVER"))
{
t = DbType.MSSQL;
}
else if (outstring.Contains("POSTGRESQL"))
{
t = DbType.POSTGRESQL;
}
}
catch (Exception E)
{
}
return t;
}
简短回答:不要。努力寻找托管的等价物。没有记录在案的获取此句柄的方法。
长答案: SQLGetInfo 函数的 InfoType 参数有 47 个可能的值。 Ref。您可以检索带引号的标识符的正则表达式模式,如下所示:
DataTable dt = connection.GetSchema(DbMetaDataCollectionNames.DataSourceInformation);
string quotedIdentifierPattern = (string)dt.Rows[0][DbMetaDataColumnNames.QuotedIdentifierPattern];
这将允许您识别但不生成带引号的标识符。不过,可以安全地假设引号字符确实是一个字符,因此您只需执行以下操作即可获得它:
Regex.Unescape(quotedIdentifierPattern)[0];
(.Unescape() 是必要的,因为引号字符可能是特殊的
正则表达式,因此逃脱了。)
SQLInfo() 的大多数其他用途同样可以通过 .GetSchema() 解决。如果
你绝对肯定必须使用 SQLGetInfo() 来做某事,我建议
使用私有方法 .GetInfoInt16Unhandled()
、.GetInfoInt32Unhandled()
和 ..GetInfoStringUnhandled()
在 OdbcConnection
上通过反思。这是
不过,可能会在没有警告的情况下破裂。
您可以通过私有.ConnectionHandle获取内部句柄
会员,但这同样容易受到破坏,而且不太方便
(因为您还必须编写所有非托管互操作代码)。
使用ILSpy or Reflector获得更多
实施细节。逆向工程的内部结构可以在许多
个案为您指明了一个完全托管的解决方案。 Ref.
OR 在此 MSDN 示例 代码的基础上构建,通过不同的命令检测版本,例如
MySQL: "SELECT version()";
甲骨文: "SELECT @@version, @@version_comment FROM dual";
SQLServer:"SELECT @@version";
using System;
using System.Data;
namespace IDbConnectionSample {
class Program {
static void Main(string[] args) {
IDbConnection connection;
// First use a SqlClient connection
connection = new System.Data.SqlClient.SqlConnection(@"Server=(localdb)\V11.0");
Console.WriteLine("SqlClient\r\n{0}", GetServerVersion(connection));
connection = new System.Data.SqlClient.SqlConnection(@"Server=(local);Integrated Security=true");
Console.WriteLine("SqlClient\r\n{0}", GetServerVersion(connection));
// Call the same method using ODBC
// NOTE: LocalDB requires the SQL Server 2012 Native Client ODBC driver
connection = new System.Data.Odbc.OdbcConnection(@"Driver={SQL Server Native Client 11.0};Server=(localdb)\v11.0");
Console.WriteLine("ODBC\r\n{0}", GetServerVersion(connection));
connection = new System.Data.Odbc.OdbcConnection(@"Driver={SQL Server Native Client 11.0};Server=(local);Trusted_Connection=yes");
Console.WriteLine("ODBC\r\n{0}", GetServerVersion(connection));
// Call the same method using OLE DB
connection = new System.Data.OleDb.OleDbConnection(@"Provider=SQLNCLI11;Server=(localdb)\v11.0;Trusted_Connection=yes;");
Console.WriteLine("OLE DB\r\n{0}", GetServerVersion(connection));
connection = new System.Data.OleDb.OleDbConnection(@"Provider=SQLNCLI11;Server=(local);Trusted_Connection=yes;");
Console.WriteLine("OLE DB\r\n{0}", GetServerVersion(connection));
}
public static string GetServerVersion(IDbConnection connection) {
// Ensure that the connection is opened (otherwise executing the command will fail)
ConnectionState originalState = connection.State;
if (originalState != ConnectionState.Open)
connection.Open();
try {
// Create a command to get the server version
IDbCommand command = connection.CreateCommand();
command.CommandText = "SELECT @@version"; //<- HERE
//try out the different commands by passing the CommandText as a parameter
return (string)command.ExecuteScalar();
}
finally {
// Close the connection if that's how we got it
if (originalState == ConnectionState.Closed)
connection.Close();
}
}
}
}
或 你可以像其他人建议的那样做一些更优雅的事情。
注意:这是对@FabianStern 的回答的复制/粘贴工作 - 感谢作者。我只是让它不那么程序化,更正统,因为我无法忍受层叠的 Try-Catch's):
protected static DBType GetDBType(string odbcConnStr)
{
var dbType = DBType.UNSUPPORTED;
try
{
using (var cn = new OdbcConnection(odbcConnStr))
{
if (cn.State != ConnectionState.Open) cn.Open();
dbType = GetDbType(cn, dbType)
if (dbType > 0) return dbType;
var sqlVersionQuery = "SELECT version()";
dbType = GetDbType(cn, sqlVersionQuery, DBType.MYSQL)
if (dbType > 0) return dbType;
sqlVersionQuery = "SELECT @@version, @@version_comment FROM dual";
dbType = GetDbType(cn, sqlVersionQuery, DBType.Oracle)
if (dbType > 0) return dbType;
sqlVersionQuery = "SELECT @@version";
dbType = GetDbType(cn, sqlVersionQuery, DBType.MSSQL)
if (dbType > 0) return dbType;
}
}
catch(Exception connEx) { }
return dbType;
}
public enum DBType
{
UNSUPPORTED = 0,
MYSQL = 1,
ORACLE = 2,
MSSQL = 3,
JET = 4
}
private static DBType GetDBType(OdbcConnection cn, DBType dbType)
{
try
{
if (cn.Driver == "odbcjt32.dll") dbType = DBType.JET;
}
catch(Exception ex) { }
return dbType;
}
private static DBType GetDbType(OdbcConnection cn, string sqlVersionQuery, DBType dbType)
{
try
{
using (var cmd = cn.CreateCommand()) {
cmd.CommandText = sqlVersionQuery;
try
{
using (var reader = cmd.ExecuteReader())
{
if (reader.HasRows) return dbType;
}
}
catch (Exception ex) { }
}}
catch (Exception cmdEx) { }
}
return dbType;
}
这绝对可以解决问题。这是我挂钩 OdbcConnection GetInfoStringUnhandled 函数的实现。上帝,我们爱倒影,我知道我是传奇 ;)
public enum SQL_INFO
{
DATA_SOURCE_NAME,
DRIVER_NAME,
DRIVER_VER,
ODBC_VER,
SERVER_NAME,
SEARCH_PATTERN_ESCAPE,
DBMS_NAME,
DBMS_VER,
IDENTIFIER_CASE,
IDENTIFIER_QUOTE_CHAR,
CATALOG_NAME_SEPARATOR,
DRIVER_ODBC_VER,
GROUP_BY,
KEYWORDS,
ORDER_BY_COLUMNS_IN_SELECT,
QUOTED_IDENTIFIER_CASE,
SQL_OJ_CAPABILITIES_30,
SQL_SQL92_RELATIONAL_JOIN_OPERATORS,
SQL_OJ_CAPABILITIES_20
}
public static string GetInfoStringUnhandled(OdbcConnection ocn, SQL_INFO info)
{
MethodInfo GetInfoStringUnhandled = ocn.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).First(c => c.Name == "GetInfoStringUnhandled");
ParameterInfo SQL_INFO =
GetInfoStringUnhandled.GetParameters()
.First(c => (c.ParameterType.ToString() == "System.Data.Odbc.ODBC32+SQL_INFO"));
Array EnumValues = SQL_INFO.ParameterType.GetEnumValues();
foreach (var enumval in EnumValues) {
if (enumval.ToString() == info.ToString()) {
return Convert.ToString(GetInfoStringUnhandled.Invoke(ocn, new object[] { enumval }));
}
}
return string.Empty;
}
private static void Main(string[] args)
{
OdbcConnection ocn = new OdbcConnection("DSN=GENESIS");
ocn.Open();
Console.WriteLine(GetInfoStringUnhandled(ocn, SQL_INFO.DBMS_VER) + " " +
GetInfoStringUnhandled(ocn, SQL_INFO.DBMS_NAME));
}
这里是我找到的最好的文档,解释了使用 SQLGetInfo 的 47 种可能性 https://mariadb.com/kb/en/sql-99/sqlgetinfo/
尽管如此,OdbcConnection 刚刚集成了一个具有 19 种可能性的枚举。以下是 SQL_INFO of System.Data.Odbc.ODBC32:
的反汇编枚举
public enum SQL_INFO : ushort
{
DATA_SOURCE_NAME = (ushort)2,
DRIVER_NAME = (ushort)6,
DRIVER_VER = (ushort)7,
ODBC_VER = (ushort)10,
SERVER_NAME = (ushort)13,
SEARCH_PATTERN_ESCAPE = (ushort)14,
DBMS_NAME = (ushort)17,
DBMS_VER = (ushort)18,
IDENTIFIER_CASE = (ushort)28,
IDENTIFIER_QUOTE_CHAR = (ushort)29,
CATALOG_NAME_SEPARATOR = (ushort)41,
DRIVER_ODBC_VER = (ushort)77,
GROUP_BY = (ushort)88,
KEYWORDS = (ushort)89,
ORDER_BY_COLUMNS_IN_SELECT = (ushort)90,
QUOTED_IDENTIFIER_CASE = (ushort)93,
SQL_OJ_CAPABILITIES_30 = (ushort)115,
SQL_SQL92_RELATIONAL_JOIN_OPERATORS = (ushort)161,
SQL_OJ_CAPABILITIES_20 = (ushort)65003
}
如您所见,您可以简单地调用 GetInfoStringUnhandled 方法,并使用您需要的信息的 (ushort) 转换整数。这是一个例子:
public static string GetInfoStringUnhandled(OdbcConnection ocn, ushort info)
{
MethodInfo GetInfoStringUnhandled = ocn.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).First(c => c.Name == "GetInfoStringUnhandled");
return Convert.ToString(GetInfoStringUnhandled.Invoke(ocn, new object[] { (ushort)info }));
}
public static void Main(string[] args)
{
OdbcConnection ocn = new OdbcConnection("DSN=GENESIS");
ocn.Open();
Console.WriteLine(GetInfoStringUnhandled(ocn, (ushort)10003)); //SQL_CATALOG_NAME returns Y
}
我开发了一个 c# 应用程序,它连接到许多类型的数据库服务器,如 Sql、Oracle、Mysql 等。连接是使用 ODBC[=29= 建立的].
我需要找到建立连接的服务器类型(DBMS 类型),因为用户只输入 DSN 名称。
经过几个小时的冲浪,我发现我的需求只能通过这个函数实现SQLGetInfo。但是我不知道如何在C#中处理这个问题。
甚至已经检查过这个Link1。
从上面link,我发现ODBC API只给出了DataBase name and DataSource Name。但是我需要找到Datatbase类型,比如它是SQL连接还是Oracle 连接或我的SqlConnection.
是否可以从 DSN 名称获取 DBMS 类型..?
注意:我不想从注册表中读取它 setting.I 尝试了这个并且它有效,但是我遇到了权限问题..!
您是否尝试解析 OdbcConnection 的 .Driver 属性? 它将向您显示连接使用的数据库包装器驱动程序。 您也可以在 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ODBC
的注册表中找到这些映射有时它只是一个 .dll 名称(例如,对于 Microsoft Excel 驱动程序),但它可以给你一个提示。
您还可以执行数据库特定命令以从服务器获取数据库版本,如下所示:
static void Main(string[] args)
{
var cn = new OdbcConnection("DSN=mysql1");
Console.WriteLine("DBType: {0}", GetDbType(cn));
Console.Read();
}
public enum DbType
{
UNSUPPORTED = 0,
MYSQL = 1,
ORACLE = 2,
MSSQL = 3,
POSTGRESQL = 4,
JET = 5
}
public static DbType GetDbType(OdbcConnection cn)
{
DbType t = DbType.UNSUPPORTED;
try
{
if (cn.State != ConnectionState.Open) cn.Open();
if (cn.Driver == "odbcjt32.dll")
{
return DbType.JET;
}
var cmd = cn.CreateCommand();
string outstring = "";
cmd.CommandText = "SELECT * FROM v$version";
try
{
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
outstring = String.Format("{0}", reader.GetString(0));
}
}
catch (Exception)
{
cmd = cn.CreateCommand();
cmd.CommandText = "SELECT @@version, @@version_comment FROM dual";
try
{
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
outstring = String.Format("{0} {1}", reader.GetString(0), reader.GetString(1));
}
}
catch (Exception)
{
cmd = cn.CreateCommand();
cmd.CommandText = "SELECT @@version";
try
{
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
outstring = String.Format("{0}", reader.GetString(0));
}
}
catch (Exception)
{
cmd = cn.CreateCommand();
cmd.CommandText = "SELECT version()";
try
{
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
outstring = String.Format("{0}", reader.GetString(0));
}
}
catch (Exception)
{
}
}
}
}
outstring = outstring.ToUpper();
if (outstring.Contains("MYSQL"))
{
t = DbType.MYSQL;
}
else if (outstring.Contains("ORACLE"))
{
t = DbType.ORACLE;
}
else if (outstring.Contains("SQL SERVER"))
{
t = DbType.MSSQL;
}
else if (outstring.Contains("POSTGRESQL"))
{
t = DbType.POSTGRESQL;
}
}
catch (Exception E)
{
}
return t;
}
简短回答:不要。努力寻找托管的等价物。没有记录在案的获取此句柄的方法。
长答案: SQLGetInfo 函数的 InfoType 参数有 47 个可能的值。 Ref。您可以检索带引号的标识符的正则表达式模式,如下所示:
DataTable dt = connection.GetSchema(DbMetaDataCollectionNames.DataSourceInformation);
string quotedIdentifierPattern = (string)dt.Rows[0][DbMetaDataColumnNames.QuotedIdentifierPattern];
这将允许您识别但不生成带引号的标识符。不过,可以安全地假设引号字符确实是一个字符,因此您只需执行以下操作即可获得它:
Regex.Unescape(quotedIdentifierPattern)[0];
(.Unescape() 是必要的,因为引号字符可能是特殊的 正则表达式,因此逃脱了。)
SQLInfo() 的大多数其他用途同样可以通过 .GetSchema() 解决。如果
你绝对肯定必须使用 SQLGetInfo() 来做某事,我建议
使用私有方法 .GetInfoInt16Unhandled()
、.GetInfoInt32Unhandled()
和 ..GetInfoStringUnhandled()
在 OdbcConnection
上通过反思。这是
不过,可能会在没有警告的情况下破裂。
您可以通过私有.ConnectionHandle获取内部句柄 会员,但这同样容易受到破坏,而且不太方便 (因为您还必须编写所有非托管互操作代码)。
使用ILSpy or Reflector获得更多 实施细节。逆向工程的内部结构可以在许多 个案为您指明了一个完全托管的解决方案。 Ref.
OR 在此 MSDN 示例 代码的基础上构建,通过不同的命令检测版本,例如
MySQL: "SELECT version()";
甲骨文: "SELECT @@version, @@version_comment FROM dual";
SQLServer:"SELECT @@version";
using System;
using System.Data;
namespace IDbConnectionSample {
class Program {
static void Main(string[] args) {
IDbConnection connection;
// First use a SqlClient connection
connection = new System.Data.SqlClient.SqlConnection(@"Server=(localdb)\V11.0");
Console.WriteLine("SqlClient\r\n{0}", GetServerVersion(connection));
connection = new System.Data.SqlClient.SqlConnection(@"Server=(local);Integrated Security=true");
Console.WriteLine("SqlClient\r\n{0}", GetServerVersion(connection));
// Call the same method using ODBC
// NOTE: LocalDB requires the SQL Server 2012 Native Client ODBC driver
connection = new System.Data.Odbc.OdbcConnection(@"Driver={SQL Server Native Client 11.0};Server=(localdb)\v11.0");
Console.WriteLine("ODBC\r\n{0}", GetServerVersion(connection));
connection = new System.Data.Odbc.OdbcConnection(@"Driver={SQL Server Native Client 11.0};Server=(local);Trusted_Connection=yes");
Console.WriteLine("ODBC\r\n{0}", GetServerVersion(connection));
// Call the same method using OLE DB
connection = new System.Data.OleDb.OleDbConnection(@"Provider=SQLNCLI11;Server=(localdb)\v11.0;Trusted_Connection=yes;");
Console.WriteLine("OLE DB\r\n{0}", GetServerVersion(connection));
connection = new System.Data.OleDb.OleDbConnection(@"Provider=SQLNCLI11;Server=(local);Trusted_Connection=yes;");
Console.WriteLine("OLE DB\r\n{0}", GetServerVersion(connection));
}
public static string GetServerVersion(IDbConnection connection) {
// Ensure that the connection is opened (otherwise executing the command will fail)
ConnectionState originalState = connection.State;
if (originalState != ConnectionState.Open)
connection.Open();
try {
// Create a command to get the server version
IDbCommand command = connection.CreateCommand();
command.CommandText = "SELECT @@version"; //<- HERE
//try out the different commands by passing the CommandText as a parameter
return (string)command.ExecuteScalar();
}
finally {
// Close the connection if that's how we got it
if (originalState == ConnectionState.Closed)
connection.Close();
}
}
}
}
或 你可以像其他人建议的那样做一些更优雅的事情。
注意:这是对@FabianStern 的回答的复制/粘贴工作 - 感谢作者。我只是让它不那么程序化,更正统,因为我无法忍受层叠的 Try-Catch's):
protected static DBType GetDBType(string odbcConnStr)
{
var dbType = DBType.UNSUPPORTED;
try
{
using (var cn = new OdbcConnection(odbcConnStr))
{
if (cn.State != ConnectionState.Open) cn.Open();
dbType = GetDbType(cn, dbType)
if (dbType > 0) return dbType;
var sqlVersionQuery = "SELECT version()";
dbType = GetDbType(cn, sqlVersionQuery, DBType.MYSQL)
if (dbType > 0) return dbType;
sqlVersionQuery = "SELECT @@version, @@version_comment FROM dual";
dbType = GetDbType(cn, sqlVersionQuery, DBType.Oracle)
if (dbType > 0) return dbType;
sqlVersionQuery = "SELECT @@version";
dbType = GetDbType(cn, sqlVersionQuery, DBType.MSSQL)
if (dbType > 0) return dbType;
}
}
catch(Exception connEx) { }
return dbType;
}
public enum DBType
{
UNSUPPORTED = 0,
MYSQL = 1,
ORACLE = 2,
MSSQL = 3,
JET = 4
}
private static DBType GetDBType(OdbcConnection cn, DBType dbType)
{
try
{
if (cn.Driver == "odbcjt32.dll") dbType = DBType.JET;
}
catch(Exception ex) { }
return dbType;
}
private static DBType GetDbType(OdbcConnection cn, string sqlVersionQuery, DBType dbType)
{
try
{
using (var cmd = cn.CreateCommand()) {
cmd.CommandText = sqlVersionQuery;
try
{
using (var reader = cmd.ExecuteReader())
{
if (reader.HasRows) return dbType;
}
}
catch (Exception ex) { }
}}
catch (Exception cmdEx) { }
}
return dbType;
}
这绝对可以解决问题。这是我挂钩 OdbcConnection GetInfoStringUnhandled 函数的实现。上帝,我们爱倒影,我知道我是传奇 ;)
public enum SQL_INFO
{
DATA_SOURCE_NAME,
DRIVER_NAME,
DRIVER_VER,
ODBC_VER,
SERVER_NAME,
SEARCH_PATTERN_ESCAPE,
DBMS_NAME,
DBMS_VER,
IDENTIFIER_CASE,
IDENTIFIER_QUOTE_CHAR,
CATALOG_NAME_SEPARATOR,
DRIVER_ODBC_VER,
GROUP_BY,
KEYWORDS,
ORDER_BY_COLUMNS_IN_SELECT,
QUOTED_IDENTIFIER_CASE,
SQL_OJ_CAPABILITIES_30,
SQL_SQL92_RELATIONAL_JOIN_OPERATORS,
SQL_OJ_CAPABILITIES_20
}
public static string GetInfoStringUnhandled(OdbcConnection ocn, SQL_INFO info)
{
MethodInfo GetInfoStringUnhandled = ocn.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).First(c => c.Name == "GetInfoStringUnhandled");
ParameterInfo SQL_INFO =
GetInfoStringUnhandled.GetParameters()
.First(c => (c.ParameterType.ToString() == "System.Data.Odbc.ODBC32+SQL_INFO"));
Array EnumValues = SQL_INFO.ParameterType.GetEnumValues();
foreach (var enumval in EnumValues) {
if (enumval.ToString() == info.ToString()) {
return Convert.ToString(GetInfoStringUnhandled.Invoke(ocn, new object[] { enumval }));
}
}
return string.Empty;
}
private static void Main(string[] args)
{
OdbcConnection ocn = new OdbcConnection("DSN=GENESIS");
ocn.Open();
Console.WriteLine(GetInfoStringUnhandled(ocn, SQL_INFO.DBMS_VER) + " " +
GetInfoStringUnhandled(ocn, SQL_INFO.DBMS_NAME));
}
这里是我找到的最好的文档,解释了使用 SQLGetInfo 的 47 种可能性 https://mariadb.com/kb/en/sql-99/sqlgetinfo/
尽管如此,OdbcConnection 刚刚集成了一个具有 19 种可能性的枚举。以下是 SQL_INFO of System.Data.Odbc.ODBC32:
的反汇编枚举public enum SQL_INFO : ushort
{
DATA_SOURCE_NAME = (ushort)2,
DRIVER_NAME = (ushort)6,
DRIVER_VER = (ushort)7,
ODBC_VER = (ushort)10,
SERVER_NAME = (ushort)13,
SEARCH_PATTERN_ESCAPE = (ushort)14,
DBMS_NAME = (ushort)17,
DBMS_VER = (ushort)18,
IDENTIFIER_CASE = (ushort)28,
IDENTIFIER_QUOTE_CHAR = (ushort)29,
CATALOG_NAME_SEPARATOR = (ushort)41,
DRIVER_ODBC_VER = (ushort)77,
GROUP_BY = (ushort)88,
KEYWORDS = (ushort)89,
ORDER_BY_COLUMNS_IN_SELECT = (ushort)90,
QUOTED_IDENTIFIER_CASE = (ushort)93,
SQL_OJ_CAPABILITIES_30 = (ushort)115,
SQL_SQL92_RELATIONAL_JOIN_OPERATORS = (ushort)161,
SQL_OJ_CAPABILITIES_20 = (ushort)65003
}
如您所见,您可以简单地调用 GetInfoStringUnhandled 方法,并使用您需要的信息的 (ushort) 转换整数。这是一个例子:
public static string GetInfoStringUnhandled(OdbcConnection ocn, ushort info)
{
MethodInfo GetInfoStringUnhandled = ocn.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).First(c => c.Name == "GetInfoStringUnhandled");
return Convert.ToString(GetInfoStringUnhandled.Invoke(ocn, new object[] { (ushort)info }));
}
public static void Main(string[] args)
{
OdbcConnection ocn = new OdbcConnection("DSN=GENESIS");
ocn.Open();
Console.WriteLine(GetInfoStringUnhandled(ocn, (ushort)10003)); //SQL_CATALOG_NAME returns Y
}