Symptomer
Når du prøver å angi et tilkoblingsattributt for en ODBC-tilkobling der tilkoblingsutvalget er aktivert ved hjelp av ODBC-driver-API-en med Microsoft SQL Server ODBC-driveren, vises følgende feilmelding:
Obs!
IM006[Microsoft][ODBC Driver Manager] Driverens SQLSetConnectAttr mislyktes
Obs! I dokumentasjonen for ODBC-driveren nevnes det at meldingen er en informasjonsmelding. Du får imidlertid meldingen som en feilmelding.
Dette problemet kan oppstå når alle følgende betingelser er oppfylt:
- Du oppretter tilkoblingen med et datakildenavn (DSN) ved hjelp av ODBC-driver-API-en SQLConnect.
- Én av standardegenskapene for DSN (for eksempel alternativet Bruk ANSI-nullverdier, utfyllinger og advarsler) er deaktivert.
- Tilkoblingsgruppering er aktivert for miljøreferansen.
- Attributtet Transaksjonsisolasjonsnivå for tilkoblingen angis når du åpner tilkoblingen ved hjelp av SQLConnect.
- En databasetransaksjon utføres.
Midlertidig løsning
Løs problemet ved å gjøre følgende:
Deaktiver alternativet for gruppering av tilkoblinger for ODBC-tilkoblingen.
Obs! Deaktivering av tilkoblingsgruppering kan påvirke ytelsen til programmet.
Når du har utført transaksjonen, må du ikke aktivere alternativet for automatisk utførelse.
Angi nivået for transaksjonsisolasjon før du åpner ODBC-tilkoblingen.
Bruk en DSN-fri tilkobling i stedet for å få ODBC-tilkoblingen med en DSN.
Oppløsning
En støttet hurtigreparasjon er tilgjengelig fra Microsoft. Denne hurtigreparasjonen er imidlertid bare ment å løse problemet som er beskrevet i denne artikkelen. Bruk denne hurtigreparasjonen bare på systemer som har dette bestemte problemet.
Hvis hurtigreparasjonen er tilgjengelig for nedlasting, finnes det en "Hurtigreparasjonsnedlasting tilgjengelig" øverst i denne Knowledge Base-artikkelen. Hvis denne delen ikke vises, sender du en forespørsel til Microsofts kundeservice og kundestøtte for å få hurtigreparasjonen.
Obs! Hvis det oppstår flere problemer eller hvis feilsøking kreves, må du kanskje opprette en egen serviceforespørsel. De vanlige støttekostnadene gjelder for flere kundestøttespørsmål og problemer som ikke kvalifiserer for denne bestemte hurtigreparasjonen. Gå til følgende Microsoft-webområde for å vise en fullstendig liste over telefonnumre for Microsofts kundeservice og kundestøtte eller opprette en separat serviceforespørsel:
http://support.microsoft.com/contactus/?ws=support Obs! Skjemaet «Hurtigreparasjonsnedlasting tilgjengelig» viser språkene som hurtigreparasjonen er tilgjengelig for. Hvis du ikke ser språket ditt, er det fordi en hurtigreparasjon ikke er tilgjengelig for dette språket. Den engelske versjonen av denne løsningen har filattributtene (eller nyere) som er oppført i tabellen nedenfor. Datoene og klokkeslettene for disse filene er oppført i koordinert universaltid (UTC). Når du viser filinformasjonen, konverteres den til lokal tid. Hvis du vil finne forskjellen mellom UTC og lokal tid, bruker du
Kategorien Tidssone i verktøyet for dato og klokkeslett i Kontrollpanel.
MDAC 2.7 SP1
Dato, klokkeslett, versjon, størrelse: Filnavn
13-Okt-2002 19:24 90,112 Dahotfix.exe
03-Jul-2003 04:09 2000.81.9031.51 372,736 Sqlsrv32.dll
MDAC 2.8
Dato, klokkeslett, versjon, størrelse: Filnavn
31-Mar-2004 16:44 2000.85.1040.0 24,576 Odbcbcp.dll
31-Mar-2004 16:43 2000.85.1040.0 401,408 Sqlsrv32.dll
Status
Microsoft har bekreftet at dette er et problem i Microsoft-produktene som er oppført i delen «Gjelder for». Dette problemet ble løst i Microsoft Data Access Component 2.7 Service Pack 1 Refresh og Microsoft Data Access Components 2.8.
Mer informasjon
Du ser problemet som er nevnt i "Symptomer"-delen i denne artikkelen, bare når du har Microsoft Data Access Component (MDAC) 2.7 Service Pack 1 installert på datamaskinen.
Trinn for å reprodusere virkemåten
Bruk følgende kode for å gjenskape problemet:
// ODBCTestCase.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
#include "sqlext.h"
#include "sql.h"
#include "stdlib.h"
void GetSQLError();
long InitializeEnvironment();
long Connect(BOOL lbUseDSN);
long Disconnect();
int ExecuteProcedure();
SQLHENV ghEnvironment = NULL;
SQLHDBC ghConnection = NULL;
HSTMT ghStatement = NULL;
/**********************************************
* main
**********************************************/
int main(int argc, char* argv[])
{
BOOL lbTransaction = TRUE;
BOOL lbUseDSN = FALSE;
long lValue =0;
if(argc > 1)
{
if(strcmp(argv[1], "DSN") == 0)
lbUseDSN = TRUE;
if(argc > 2)
{
if(strcmp(argv[2], "TRAN") == 0)
lbTransaction = TRUE;
}
}
if(InitializeEnvironment() == 0)
{
for(long llSub = 0; llSub < 2; llSub++)
{
if(Connect(lbUseDSN) == 0)
{
if(lbTransaction)
SQLSetConnectOption(ghConnection, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);
//SQLGetConnectAttr(ghConnection,SQL_ATTR_AUTOCOMMIT,&lValue,0,NULL);
ExecuteProcedure();
if(lbTransaction)
{
SQLTransact(ghEnvironment, ghConnection, SQL_COMMIT);
//If you do not call the following, the problem does not occur:
SQLSetConnectOption(ghConnection, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_ON);
//If you call the following the problem does not occur:
//SQLSetConnectOption(ghConnection, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);
//SQLGetConnectAttr(ghConnection,SQL_ATTR_AUTOCOMMIT,&lValue,0,NULL);
}
Disconnect();
}
}
SQLFreeHandle(SQL_HANDLE_ENV, ghEnvironment);
}
return 0;
}
/**********************************************
* InitializeEnvironment
**********************************************/
long InitializeEnvironment()
{
if (!SQL_SUCCEEDED(SQLSetEnvAttr(NULL,
SQL_ATTR_CONNECTION_POOLING,
(SQLPOINTER)SQL_CP_ONE_PER_DRIVER,
SQL_IS_INTEGER)))
{
GetSQLError();
return 8;
}
if(!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_ENV, NULL, &ghEnvironment)))
{
GetSQLError();
return 8;
}
if(!SQL_SUCCEEDED(SQLSetEnvAttr(ghEnvironment, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC2, SQL_IS_INTEGER)))
{
GetSQLError();
return 8;
}
if (!SQL_SUCCEEDED(SQLSetEnvAttr(ghEnvironment,
SQL_ATTR_CP_MATCH,
(SQLPOINTER) SQL_CP_STRICT_MATCH ,
//(SQLPOINTER) SQL_CP_RELAXED_MATCH ,
SQL_IS_INTEGER)))
{
GetSQLError();
return 8;
}
return 0;
}
/**********************************************
* Connect
**********************************************/
long Connect(BOOL lbUseDSN)
{
SQLCHAR lszOutConnectString[1024];
SQLSMALLINT llReturnLength;
SQLAllocHandle(SQL_HANDLE_DBC, ghEnvironment, &ghConnection);
// If you set the isolation before opening the connection, no error reported.
// Customer cannot set this attribute before opening connection because the object
//is running under COM+, and under COM+ isolation levels automatically are set to serializable
//if(!SQL_SUCCEEDED(::SQLSetConnectAttr(ghConnection, SQL_ATTR_TXN_ISOLATION, (SQLPOINTER)SQL_TXN_READ_COMMITTED , SQL_IS_INTEGER)))
//{
// GetSQLError();
// return 8;
//}
if(lbUseDSN)
{
int iReturn = ::SQLConnect(ghConnection,
(SQLCHAR*)"LocalCPR",
SQL_NTS,
(SQLCHAR*)"sa",
SQL_NTS,
(SQLCHAR*)"password1",
SQL_NTS);
if(!SQL_SUCCEEDED(iReturn))
{
GetSQLError();
return 8;
}
}
else
{
if(!SQL_SUCCEEDED(SQLDriverConnect(ghConnection,
NULL,
(SQLCHAR*)"DSN=LocalCPR;UID=sa;PWD=password1;",
SQL_NTS,
lszOutConnectString,
1024,
&llReturnLength,
SQL_DRIVER_NOPROMPT)))
{
GetSQLError();
return 8;
}
}
SQLAllocStmt(ghConnection, &ghStatement);
//If you set the isolation after you open the connection, you see the problem.
if(!SQL_SUCCEEDED(::SQLSetConnectAttr(ghConnection, SQL_ATTR_TXN_ISOLATION, (SQLPOINTER)SQL_TXN_READ_COMMITTED , SQL_IS_INTEGER)))
{
GetSQLError();
return 8;
}
return 0;
}
/**********************************************
* Disconnect
**********************************************/
long Disconnect()
{
if(ghStatement)
{
if(!SQL_SUCCEEDED(SQLFreeHandle(SQL_HANDLE_STMT, ghStatement)))
{
GetSQLError();
return 8;
}
ghStatement = NULL;
}
if(ghConnection)
{
::SQLDisconnect(ghConnection);
if(!SQL_SUCCEEDED(SQLFreeHandle(SQL_HANDLE_DBC, ghConnection)))
{
GetSQLError();
return 8;
}
ghConnection = NULL;
}
return 0;
}
/**********************************************
* ExecuteProcedure
**********************************************/
int ExecuteProcedure()
{
SQLINTEGER mlIndicator = 0;
SQLRETURN lnSqlRetCd = SQL_SUCCESS;
::SQLFreeStmt(ghStatement, SQL_CLOSE);
::SQLFreeStmt(ghStatement, SQL_UNBIND);
/*****************************************************************/
/* Execute Procedure
/*****************************************************************/
RETCODE llDbRetCd = SQLExecDirect(ghStatement, (SQLCHAR*)"SELECT * From Table1", SQL_NTS);
if((llDbRetCd != SQL_SUCCESS) && (llDbRetCd != SQL_SUCCESS_WITH_INFO))
{
GetSQLError();
return 8;
}
/*****************************************************************/
/* Bind return Value
/*****************************************************************/
char lszReturnBuf[300];
SDWORD lSts;
llDbRetCd = SQLBindCol(ghStatement, 1, SQL_C_TCHAR, &lszReturnBuf, 300, &lSts);
if ((llDbRetCd != SQL_SUCCESS) && (llDbRetCd != SQL_SUCCESS_WITH_INFO))
{
GetSQLError();
return 8;
}
/*****************************************************************/
/* Fetch Result
/*****************************************************************/
llDbRetCd = SQLFetch(ghStatement);
if ((llDbRetCd != SQL_SUCCESS) && (llDbRetCd != SQL_SUCCESS_WITH_INFO))
{
GetSQLError();
return 8;
}
printf("Output Value : %s\n",lszReturnBuf);
return 0;
}
/**********************************************
* GetSQLError
**********************************************/
void GetSQLError()
{
long llDbErrCd = 0;
short llRetMsgLen = 0;
char lszSqlErrMsg[255];
char lszSqlMsg[255];
SQLError(ghEnvironment,
ghConnection,
ghStatement,
(SQLCHAR*) lszSqlErrMsg,
&llDbErrCd,
(SQLCHAR*) lszSqlMsg,
255,
&llRetMsgLen);
printf(lszSqlErrMsg);
printf(lszSqlMsg);
}