Risposta breve: non lo fanno. Cerca molto difficile trovare equivalenti gestiti invece. Non esiste un modo documentato per ottenere questo handle.
Risposta lunga: Il parametro InfoType della funzione SQLGetInfo ha 47 valori possibili. Ref. È possibile recuperare un modello di espressione regolare per identificatori tra virgolette come segue:
DataTable dt = connection.GetSchema(DbMetaDataCollectionNames.DataSourceInformation);
string quotedIdentifierPattern = (string)dt.Rows[0][DbMetaDataColumnNames.QuotedIdentifierPattern];
Questo vi permetterà di riconoscere, ma non produce identificatori tra virgolette. E 'lecito ritenere il carattere di citazione è davvero un personaggio, però, così si può ottenere semplicemente facendo:
Regex.Unescape(quotedIdentifierPattern)[0];
(The .Unescape() è necessaria in quanto il carattere preventivo potrebbe essere speciale per regexen e, quindi, escape.)
La maggior parte degli altri usi di SQLInfo() può essere risolta in modo simile con .GetSchema(). Se si assolutamente, positivamente necessario utilizzare SQLGetInfo() per qualcosa, vi consiglio utilizzando i metodi privati .GetInfoInt16Unhandled()
, .GetInfoInt32Unhandled()
e ..GetInfoStringUnhandled()
su OdbcConnection
attraverso la riflessione. Questo è soggetto a rottura senza preavviso, però.
è possibile ottenere la maniglia interna attraverso il privato .ConnectionHandle membro, ma questo è ugualmente soggetto alla rottura e di gran lunga meno conveniente (perché devi scrivere tutto il codice di interoperabilità non gestito troppo).
Utilizzare ILSpy o Reflector per ottenere ulteriori dettagli sull'implementazione. Il reverse engineering degli interni può in molti casi indirizzarvi verso una soluzione completamente gestita. Ref.
O build su questo MSDN codice di esempio per rilevare la versione tramite diversi comandi, ad esempio
MySQL: "versione SELECT()";
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();
}
}
}
}
O si potrebbe fare qualcosa di simile altri suggeriscono, con un po 'più di eleganza.
Nota: questo è un lavoro di copia/incolla sulla risposta di @FabianStern - credito all'autore. Ho appena fatto meno procedurale e più ortodossa come non ho potuto resistere alla cascata del try-catch):
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;
}
Qual è il punto della domanda .. Non intendo questo condiscendente. Con tutto il dovuto rispetto perché non usi il pattern IDBConnection ** Factory **? In questo modo non hai bisogno di conoscere il produttore del DB e devi solo scrivere un DAL? A meno che non si stia scrivendo un ORM, si tratta di un enorme overhead che si rivolge a diversi DB e non ha molto guadagno, specialmente quando non si sta facendo qualcosa di troppo specifico. EF, Mindscape LightSpeed, Hibernate, ecc. Offrono tutte soluzioni migliori - MA anche questi prodotti richiedono agli utenti finali di specificare manualmente il tipo di database. –