Короткий ответ: не делать. Попробуйте очень трудно найти управляемые эквиваленты. Нет документального способа получения этого дескриптора.
Длинный ответ: Параметр InfoType функции SQLGetInfo имеет 47 возможных значений. Ref. Вы можете получить регулярное выражение для цитируемых идентификаторов следующим образом:
DataTable dt = connection.GetSchema(DbMetaDataCollectionNames.DataSourceInformation);
string quotedIdentifierPattern = (string)dt.Rows[0][DbMetaDataColumnNames.QuotedIdentifierPattern];
Это позволит вам распознать, но не производить идентификаторы в кавычках. Это с уверенностью предположить, котировка характер действительно один персонаж, хотя, так что вы можете получить его просто делать:
Regex.Unescape(quotedIdentifierPattern)[0];
(.Unescape() является необходимым, так как кавычка может быть особенным regexen и, следовательно, escaped.)
Большинство других применений для SQLInfo() можно аналогичным образом решить с помощью .GetSchema(). Если вы абсолютно положительно должны использовать SQLGetInfo() что-то я рекомендую , используя частные методы .GetInfoInt16Unhandled()
, .GetInfoInt32Unhandled()
и ..GetInfoStringUnhandled()
на OdbcConnection
посредством отражения. Это , подлежащие разрыву без предупреждения.
Вы можете получить внутреннюю ручку через частный .ConnectionHandle члена, но это в равной степени подвержены нарушения и гораздо менее удобно (потому что вы должны написать все неуправляемый код Interop тоже).
Используйте ILSpy или Reflector, чтобы получить более подробное описание . Обратное проектирование внутренних дел во многих случаях указывает на полностью управляемое решение. Ref.
ИЛИ сборки на этом MSDN образец кода для обнаружения версии с помощью различных команд, например
MySQL: "ВЫБОР версии()";
Oracle: "SELECT @@ version, @@ version_comment FROM dual";
SQLServer: "SELECT @@ version";
MSDN Sample Code:
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-Поймай в):
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;
}
В чем дело. Я не имею в виду это снисходительно. При всем уважении, почему вы не используете шаблон IDBConnection ** Factory **? Таким образом, вам не нужно знать производителя БД и нужно только написать один DAL? Если вы не пишете ORM, это огромные накладные расходы, предназначенные для разных БД, и для получения большого выигрыша - особенно если вы не делаете ничего слишком специфического. EF, Mindscape LightSpeed, Hibernate и т. Д. Предлагают лучшие решения - даже если эти продукты требуют, чтобы конечные пользователи вручную указывали тип базы данных. –