Příznaky
Při pokusu nastavit atribut připojení připojení ODBC sdružování připojení kde je povoleno pomocí rozhraní API ODBC ovladač s ovladačem ODBC Microsoft SQL Server, zobrazí se následující chybová zpráva:
IM006 SQLSetConnectAttr ovladač [Microsoft] [správce ovladačů ODBC] se nezdařilo
Poznámka: V dokumentaci k ovladači ODBC uvádí, že zpráva je informační zpráva. Však obdržíte zprávu jako chybová zpráva.
Tomuto problému může dojít, pokud jsou splněny následující podmínky:
-
Vytváření připojení pomocí název zdroje dat (DSN) pomocí rozhraní API ODBC ovladač SQLConnect.
-
Některé vlastnosti výchozí název zdroje dat (například možnost použití ANSI hodnoty Null, výplně a upozornění ) je zakázána.
-
Je povoleno sdružování připojení pro popisovač prostředí.
-
Po otevření připojení pomocí SQLConnect je nastaven atribut úroveň izolace transakce připojení.
-
Databázové transakce provedena.
Jak potíže obejít
Chcete-li tento problém vyřešit, postupujte takto:
-
Zakážete sdružování připojení ODBC připojení.
Poznámka: Zakázat sdružování připojení může ovlivnit výkon aplikace. -
Po potvrzení transakce nezapínejte možnost automatického potvrzení.
-
Nastavte úroveň izolace transakcí před otevřením připojení ODBC.
-
Připojení bez DSN použijte namísto získání připojení ODBC pomocí názvu DSN.
Řešení
Společnost Microsoft má k dispozici podporovanou opravu hotfix. Tato oprava hotfix je však určena pouze problému popsanému v tomto článku. Použití této opravy hotfix pouze u systémů, ve kterých dochází k tomuto konkrétnímu problému.
Pokud je oprava hotfix k dispozici ke stažení, je v horní části tohoto článku znalostní báze Knowledge Base oddíl "Oprava Hotfix je dostupná ke stažení" . Pokud tento oddíl není uveden, odešlete požadavek na Microsoft Zákaznický servis a podporu k získání opravy hotfix.
Poznámka: Pokud nastanou další problémy nebo bude nutné další řešení potíží, bude možná třeba vytvořit další samostatný požadavek na služby. Běžná cena za technickou podporu se vztahuje k dodatečným otázkám podpory a k problémům, které se netýkají této konkrétní opravy hotfix. Úplný seznam telefonních čísel služeb zákazníkům společnosti Microsoft a podpoře nebo vytvořit zvláštní požadavek na službu naleznete na následujícím webu společnosti Microsoft:
http://support.microsoft.com/contactus/?ws=supportPoznámka: Ve formuláři „Oprava hotfix je dostupná ke stažení“ se zobrazují jazyky, pro které je oprava hotfix k dispozici. Pokud váš jazyk není zobrazen, to je protože oprava hotfix není k dispozici pro daný jazyk. Anglická verze této opravy má atributy souborů (nebo novější) uvedené v následující tabulce. Kalendářní data a časy jednotlivých souborů jsou uvedeny v koordinovaném světovém čase (UTC). Při zobrazení informací o souboru je převeden na místní čas. Chcete-li najít rozdíl mezi místním časem a UTC, použijte
Časové pásmo karta v nástroji datum a čas v okně Ovládací panely.
MDAC 2.7 SP1
Date Time Version Size File name
--------------------------------------------------------
13-Oct-2002 19:24 90,112 Dahotfix.exe
03-Jul-2003 04:09 2000.81.9031.51 372,736 Sqlsrv32.dll
MDAC 2.8
Date Time Version Size File name
--------------------------------------------------------
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
Poznámka: Seznam oprav hotfix dostupných pro součásti MDAC 2.8 klepněte na následující číslo článku databáze Microsoft Knowledge Base:
839801 oprava: opravy hotfix jsou k dispozici pro součásti MDAC 2.8
Stav
Společnost Microsoft potvrzuje, že se jedná o problém v produktech této společnosti, které jsou uvedeny v části "Platí pro". Tento problém byl opraven v Microsoft Data Access součásti 2.7 Service Pack 1 aktualizovat a Microsoft Data Access Components 2.8.
Další informace
Dochází k potížím, která je uvedena v části "Příznaky" tohoto článku, pouze pokud máte Microsoft Data Access Component (MDAC) 2.7 Service Pack 1 v počítači nainstalována.
Kroky pro reprodukci chování
Pro reprodukci tohoto problému použijte následující kód:
// 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);
}