Megosztás:


Aszinkron végrehajtás (lekérdezési módszer)

Az ODBC 3.8 és a Windows 7 SDK előtt az aszinkron műveletek csak utasításfüggvényeken voltak engedélyezettek. További információ: A végrehajtási utasítás műveletei aszinkron módon, a jelen témakör későbbi részében.

A Windows 7 SDK-ban az ODBC 3.8 aszinkron végrehajtást vezetett be a kapcsolattal kapcsolatos műveleteken. További információ: A kapcsolati műveletek aszinkron végrehajtása szakasz, amely a jelen témakör későbbi részében található.

A Windows 7 SDK-ban az aszinkron utasítás vagy kapcsolati műveletek esetében egy alkalmazás megállapította, hogy az aszinkron művelet befejeződött a lekérdezési módszerrel. A Windows 8 SDK-tól kezdve megállapíthatja, hogy az aszinkron művelet befejeződött-e az értesítési módszerrel. További információt az Aszinkron végrehajtás (Értesítési módszer) című témakörben talál.

Alapértelmezés szerint az illesztőprogramok szinkron módon hajtják végre az ODBC-függvényeket; vagyis az alkalmazás meghív egy függvényt, és az illesztő addig nem adja vissza az irányítást az alkalmazásnak, amíg be nem fejeződik a függvény végrehajtása. Egyes függvények azonban aszinkron módon is végrehajthatók; vagyis az alkalmazás meghívja a függvényt, és az illesztőprogram minimális feldolgozás után visszaadja az irányítást az alkalmazásnak. Az alkalmazás ezután meghívhat más függvényeket, miközben az első függvény továbbra is fut.

Az aszinkron végrehajtás a legtöbb olyan függvény esetében támogatott, amelyeket nagyrészt az adatforráson hajtanak végre, például a kapcsolatok létrehozásához, AZ SQL-utasítások előkészítéséhez és végrehajtásához, a metaadatok lekéréséhez, az adatok lekéréséhez és a tranzakciók véglegesítéséhez. Ez akkor hasznos, ha az adatforráson végrehajtott feladat hosszú időt vesz igénybe, például egy bejelentkezési folyamatot vagy egy összetett lekérdezést egy nagy adatbázison.

Amikor az alkalmazás egy olyan utasítással vagy kapcsolattal hajt végre egy függvényt, amely engedélyezett az aszinkron feldolgozásra, az illesztőprogram minimális mennyiségű feldolgozást végez el (például az érvek hibáinak ellenőrzését), majd átadja a feldolgozást az adatforrásnak, és visszaadja az irányítást az alkalmazásnak a SQL_STILL_EXECUTING visszatérési kóddal. Az alkalmazás ezután más feladatokat is végrehajt. Annak megállapításához, hogy az aszinkron függvény mikor fejeződött be, az alkalmazás rendszeres időközönként lekérdezi az illesztőprogramot úgy, hogy a függvényt ugyanazokkal az argumentumokkal hívja meg, mint az eredetileg használt. Ha a függvény továbbra is fut, visszaadja az SQL_STILL_EXECUTING értéket; ha befejezte a végrehajtást, visszaadja azt a kódot, amit szinkron végrehajtásnál adna vissza, például SQL_SUCCESS, SQL_ERROR vagy SQL_NEED_DATA.

Az illesztőprogram-specifikus, hogy egy függvény szinkron vagy aszinkron módon fut-e. Tegyük fel például, hogy az eredményhalmaz metaadatai gyorsítótárazva lesznek az illesztőprogramban. Ebben az esetben nagyon kevés időt vesz igénybe az SQLDescribeCol végrehajtása, és az illesztőnek egyszerűen végre kell hajtania a függvényt ahelyett, hogy mesterségesen késlelteti a végrehajtást. Ha viszont az illesztőprogramnak le kell kérnie a metaadatokat az adatforrásból, akkor vissza kell adnia az irányítást az alkalmazásnak, miközben ezt teszi. Ezért az alkalmazásnak képesnek kell lennie a SQL_STILL_EXECUTING kívüli visszatérési kódot kezelni, amikor először hajt végre egy függvényt aszinkron módon.

Utasításműveletek aszinkron végrehajtása

Az alábbi utasításfüggvények egy adatforráson működnek, és aszinkron módon hajthatók végre:

Az aszinkron utasítás végrehajtása utasításonként vagy kapcsolatonkénti alapon történik, az adatforrástól függően. Vagyis az alkalmazás nem azt határozza meg, hogy egy adott függvényt aszinkron módon kell végrehajtani, hanem azt, hogy az adott utasításon végrehajtott összes függvényt aszinkron módon kell végrehajtani. Annak kiderítéséhez, hogy melyik támogatott, egy alkalmazás meghívja az SQLGetInfo-t egy SQL_ASYNC_MODE lehetőséggel. SQL_AM_CONNECTION értéket ad vissza, ha a kapcsolatszintű aszinkron végrehajtás (utasításkezelő esetében) támogatott; SQL_AM_STATEMENT értéket ad vissza, ha az utasításszintű aszinkron végrehajtás támogatott.

Annak megadásához, hogy az adott utasítással végrehajtott függvényeket aszinkron módon kell végrehajtani, az alkalmazás meghívja az SQLSetStmtAttr parancsot a SQL_ATTR_ASYNC_ENABLE attribútummal, és beállítja azt SQL_ASYNC_ENABLE_ON. Ha támogatott a kapcsolatszinten történő aszinkron feldolgozás, az SQL_ATTR_ASYNC_ENABLE utasítás attribútuma írásvédett, és az értéke megegyezik annak a kapcsolatnak az attribútumával, amelyhez az utasítást lefoglalták. Illesztőprogram-specifikus, hogy az utasításattribútum értéke az utasításfoglalási időpontban vagy későbbi időpontban van-e beállítva. A beállítás megkísérlése SQL_ERROR és SQLSTATE HYC00 értéket ad vissza (a választható funkció nem implementálva).

Annak megadásához, hogy az adott kapcsolattal végrehajtott függvényeket aszinkron módon kell végrehajtani, az alkalmazás meghívja az SQLSetConnectAttr parancsot a SQL_ATTR_ASYNC_ENABLE attribútummal, és beállítja azt SQL_ASYNC_ENABLE_ON. A kapcsolaton lefoglalt összes jövőbeli utasításkezelő engedélyezve lesz az aszinkron végrehajtáshoz; az illesztőprogram határozza meg, hogy a művelet engedélyezi-e a meglévő utasításkezelőket. Ha SQL_ATTR_ASYNC_ENABLE SQL_ASYNC_ENABLE_OFF van beállítva, a kapcsolat összes utasítása szinkron módban van. Hiba jelenik meg, ha az aszinkron végrehajtás engedélyezve van, miközben aktív utasítás van a kapcsolaton.

Ha meg szeretné határozni az aktív egyidejű utasítások maximális számát aszinkron módban, amelyet az illesztőprogram támogatni tud egy adott kapcsolaton, az alkalmazás meghívja az SQLGetInfo-t a SQL_MAX_ASYNC_CONCURRENT_STATEMENTS beállítással.

Az alábbi kód bemutatja a lekérdezési modell működését:

SQLHSTMT  hstmt1;  
SQLRETURN rc;  
  
// Specify that the statement is to be executed asynchronously.  
SQLSetStmtAttr(hstmt1, SQL_ATTR_ASYNC_ENABLE, SQL_ASYNC_ENABLE_ON, 0);  
  
// Execute a SELECT statement asynchronously.  
while ((rc=SQLExecDirect(hstmt1,"SELECT * FROM Orders",SQL_NTS))==SQL_STILL_EXECUTING) {  
   // While the statement is still executing, do something else.  
   // Do not use hstmt1, because it is being used asynchronously.  
}  
  
// When the statement has finished executing, retrieve the results.  

Bár egy függvény aszinkron módon hajt végre műveleteket, az alkalmazás bármilyen más utasításban meghívhat függvényeket. Az alkalmazás bármilyen kapcsolaton meghívhat függvényeket, kivéve az aszinkron utasításhoz társított függvényt. Az alkalmazás azonban csak az eredeti függvényt és a következő függvényeket hívhatja meg (az utasításkezelővel vagy a hozzá tartozó kapcsolattal, környezeti leíróval), miután egy utasításművelet SQL_STILL_EXECUTING értéket ad vissza.

Ha az alkalmazás más függvényeket hív meg az aszinkron utasítással vagy az utasításhoz társított kapcsolattal, a függvény például SQLSTATE HY010 -t (függvényütemezési hibát) ad vissza.

SQLHDBC       hdbc1, hdbc2;  
SQLHSTMT      hstmt1, hstmt2, hstmt3;  
SQLCHAR *     SQLStatement = "SELECT * FROM Orders";  
SQLUINTEGER   InfoValue;  
SQLRETURN     rc;  
  
SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1);  
SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt2);  
SQLAllocHandle(SQL_HANDLE_STMT, hdbc2, &hstmt3);  
  
// Specify that hstmt1 is to be executed asynchronously.  
SQLSetStmtAttr(hstmt1, SQL_ATTR_ASYNC_ENABLE, SQL_ASYNC_ENABLE_ON, 0);  
  
// Execute hstmt1 asynchronously.  
while ((rc = SQLExecDirect(hstmt1, SQLStatement, SQL_NTS)) == SQL_STILL_EXECUTING) {  
   // The following calls return HY010 because the previous call to  
   // SQLExecDirect is still executing asynchronously on hstmt1. The  
   // first call uses hstmt1 and the second call uses hdbc1, on which  
   // hstmt1 is allocated.  
   SQLExecDirect(hstmt1, SQLStatement, SQL_NTS);   // Error!  
   SQLGetInfo(hdbc1, SQL_UNION, (SQLPOINTER) &InfoValue, 0, NULL);   // Error!  
  
   // The following calls do not return errors. They use a statement  
   // handle other than hstmt1 or a connection handle other than hdbc1.  
   SQLExecDirect(hstmt2, SQLStatement, SQL_NTS);   // OK  
   SQLTables(hstmt3, NULL, 0, NULL, 0, NULL, 0, NULL, 0);   // OK  
   SQLGetInfo(hdbc2, SQL_UNION, (SQLPOINTER) &InfoValue, 0, NULL);   // OK  
}  

Amikor egy alkalmazás meghív egy függvényt annak meghatározására, hogy továbbra is aszinkron módon hajtja-e végre, az eredeti utasításkezelőt kell használnia. Ennek az az oka, hogy az aszinkron végrehajtást utasításonként követi nyomon a program. Az alkalmazásnak érvényes értékeket is meg kell adnia a többi argumentumhoz – az eredeti argumentumok is megfelelőek –, hogy az illesztőprogram-kezelő hibaellenőrzésén átjusson. Miután azonban az illesztőprogram ellenőrizte az utasításkezelőt, és megállapította, hogy az utasítás aszinkron módon fut, figyelmen kívül hagyja az összes többi argumentumot.

Bár egy függvény aszinkron módon hajt végre – vagyis miután visszaadta SQL_STILL_EXECUTING, és mielőtt egy másik kódot ad vissza – az alkalmazás megszakíthatja azt az SQLCancel vagy az SQLCancelHandle ugyanazzal az utasításkezelővel történő meghívásával. Ez nem garantálja a függvény végrehajtásának megszakítását. Előfordulhat például, hogy a függvény már befejeződött. Továbbá az SQLCancel vagy az SQLCancelHandle által visszaadott kód csak azt jelzi, hogy a függvény megszakítására tett kísérlet sikeres volt-e, nem pedig azt, hogy valóban megszakította-e a függvényt. Annak megállapításához, hogy a függvényt visszavonták-e, az alkalmazás ismét meghívja a függvényt. Ha a függvényt megszakították, SQL_ERROR és SQLSTATE HY008 értéket ad vissza (a művelet megszakítva). Ha a függvény nem lett megszakítva, egy másik kódot ad vissza, például SQL_SUCCESS, SQL_STILL_EXECUTING vagy SQL_ERROR egy másik SQLSTATE-vel.

Ha le szeretné tiltani egy adott utasítás aszinkron végrehajtását, amikor az illesztőprogram támogatja az utasításszintű aszinkron feldolgozást, az alkalmazás meghívja az SQLSetStmtAttr-t az SQL_ATTR_ASYNC_ENABLE attribútummal, és beállítja azt SQL_ASYNC_ENABLE_OFF. Ha az illesztőprogram támogatja a kapcsolatszintű aszinkron feldolgozást, az alkalmazás meghívja az SQLSetConnectAttr-t , hogy állítsa SQL_ATTR_ASYNC_ENABLE SQL_ASYNC_ENABLE_OFF értékre, ami letiltja a kapcsolat összes utasításának aszinkron végrehajtását.

Az alkalmazásnak az eredeti függvény ismétlődő ciklusában kell feldolgoznia a diagnosztikai rekordokat. Ha az SQLGetDiagField vagy az SQLGetDiagRec aszinkron függvény végrehajtásakor van meghívva, az a diagnosztikai rekordok aktuális listáját adja vissza. Minden alkalommal, amikor az eredeti függvényhívás ismétlődik, törli a korábbi diagnosztikai rekordokat.

Kapcsolati műveletek aszinkron végrehajtása

Az ODBC 3.8 előtt az aszinkron végrehajtás engedélyezett volt az utasításokkal kapcsolatos műveletek, például az előkészítés, a végrehajtás és a beolvasás, valamint a katalógus metaadatainak műveletei esetében. Az ODBC 3.8-tól kezdődően aszinkron végrehajtás is lehetséges a kapcsolattal kapcsolatos műveletekhez, például a csatlakozáshoz, a leválasztáshoz, a véglegesítéshez és a visszaállításhoz.

További információ az ODBC 3.8-ról: Az ODBC 3.8 újdonságai.

A kapcsolati műveletek aszinkron végrehajtása a következő esetekben hasznos:

  • Ha egy kis számú szál nagy számú eszközt kezel nagyon magas adatsebességgel. A válaszkészség és a méretezhetőség maximalizálása érdekében minden műveletnek aszinkronnak kell lennie.

  • Ha több kapcsolaton szeretné átfedni az adatbázisműveleteket az eltelt átviteli idő csökkentése érdekében.

  • A hatékony aszinkron ODBC-hívások és a kapcsolati műveletek megszakításának lehetősége lehetővé teszi, hogy a felhasználó időtúllépések nélkül megszakítsa a lassú műveletet.

A kapcsolati leírókon működő alábbi függvények mostantól aszinkron módon végrehajthatók:

Annak megállapításához, hogy egy illesztőprogram támogatja-e az aszinkron műveleteket ezeken a függvényeken, egy alkalmazás meghívja az SQLGetInfo-t SQL_ASYNC_DBC_FUNCTIONS. Ha az aszinkron műveletek támogatottak, akkor az SQL_ASYNC_DBC_CAPABLE kerül visszaadásra. SQL_ASYNC_DBC_NOT_CAPABLE akkor adódik vissza, ha az aszinkron műveletek nem támogatottak.

Annak megadásához, hogy az adott kapcsolattal végrehajtott függvényeket aszinkron módon kell végrehajtani, az alkalmazás meghívja az SQLSetConnectAttr parancsot , és beállítja a SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE attribútumot SQL_ASYNC_DBC_ENABLE_ON. A kapcsolatattribútum beállítása a kapcsolat létrehozása előtt mindig szinkron módon történik. Emellett az SQLSetConnectAttr SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE kapcsolatattribútumot állító művelet mindig szinkron módon hajtja végre.

Az alkalmazások a kapcsolat létrehozása előtt engedélyezhetik az aszinkron műveletet. Mivel az illesztőprogram-kezelő nem tudja meghatározni, hogy melyik illesztőprogramot használja a kapcsolat létrehozása előtt, az illesztőprogram-kezelő mindig sikeres lesz az SQLSetConnectAttr alkalmazásban. Előfordulhat azonban, hogy nem tud csatlakozni, ha az ODBC-illesztő nem támogatja az aszinkron műveleteket.

Általában legfeljebb egy aszinkron végrehajtó függvény lehet egy adott kapcsolati leíróhoz vagy utasításkezelőhöz társítva. Egy kapcsolatleíró azonban több társított utasításfogóval is rendelkezhet. Ha a kapcsolati leírón nem fut aszinkron művelet, a társított utasításkezelők aszinkron műveletet hajthatnak végre. Hasonlóképpen aszinkron műveletet is végezhet egy kapcsolati leírón, ha nincs folyamatban aszinkron művelet a társított utasításleírókon. Ha egy aszinkron műveletet egy olyan fogantyúval kísérel meg végrehajtani, amely jelenleg aszinkron műveletet hajt végre, a HY010 (Függvénysorozat-hiba) értéket adja vissza.

Ha egy kapcsolati művelet SQL_STILL_EXECUTING ad vissza, az alkalmazás csak az eredeti függvényt és a következő függvényeket hívhatja meg a kapcsolati leíróhoz:

  • SQLCancelHandle (a kapcsolati leírón)

  • SQLGetDiagField

  • SQLGetDiagRec

  • SQLAllocHandle (AZ ENV/DBC kiosztása)

  • SQLAllocHandleStd (a ENV/DBC kiosztása)

  • SQLGetEnvAttr

  • SQLGetConnectAttr

  • SQLDataSources

  • SQLDrivers

  • SQLGetInfo

  • SQLGetFunctions

Az alkalmazásnak az eredeti függvény ismétlődő ciklusában kell feldolgoznia a diagnosztikai rekordokat. Ha az SQLGetDiagField vagy az SQLGetDiagRec aszinkron függvény végrehajtásakor van meghívva, az a diagnosztikai rekordok aktuális listáját adja vissza. Minden alkalommal, amikor az eredeti függvényhívás ismétlődik, törli a korábbi diagnosztikai rekordokat.

Ha a kapcsolat aszinkron módon van megnyitva vagy lezárva, a művelet akkor fejeződik be, ha az alkalmazás SQL_SUCCESS vagy SQL_SUCCESS_WITH_INFO fogad az eredeti függvényhívásban.

Új függvény lett hozzáadva az SQLCancelHandle ODBC 3.8-hoz. Ez a függvény megszakítja a hat kapcsolati függvényt (SQLBrowseConnect, SQLConnect, SQLDisconnect, SQLDriverConnect, SQLEndTran és SQLSetConnectAttr). Az alkalmazásnak meg kell hívnia az SQLGetFunctionset annak megállapításához, hogy az illesztőprogram támogatja-e az SQLCancelHandle-t. Az SQLCancelhez hasonlóan, ha az SQLCancelHandle sikert ad vissza, az nem jelenti azt, hogy a művelet megszakadt. Egy alkalmazásnak újra meg kell hívnia az eredeti függvényt annak megállapításához, hogy a művelet megszakadt-e. Az SQLCancelHandle lehetővé teszi az aszinkron műveletek megszakítását a kapcsolati leírókon vagy utasításkezelőkön. Ha az SQLCancelHandle használatával megszakít egy műveletet egy utasításleírón, ugyanaz, mint az SQLCancel hívása.

Nem szükséges egyszerre támogatni az SQLCancelHandle és az aszinkron kapcsolati műveleteket. Az illesztőprogramok támogathatják az aszinkron kapcsolati műveleteket, az SQLCancelHandle-t azonban nem, vagy fordítva.

Az aszinkron kapcsolati műveleteket és az SQLCancelHandle-t az ODBC 3.x és ODBC 2.x alkalmazások is használhatják ODBC 3.8 illesztőprogrammal és ODBC 3.8 Driver Managerrel. Ha tudni szeretné, hogyan engedélyezheti egy régebbi alkalmazásnak az új funkciók használatát a későbbi ODBC-verzióban, olvassa el a Kompatibilitási mátrixot.

Kapcsolatkészletezés

Ha engedélyezve van a kapcsolatkészletezés, az aszinkron műveletek csak minimálisan támogatottak a kapcsolat létrehozásához ( az SQLConnect és az SQLDriverConnect használatával) és az SQLDisconnecttel való kapcsolat bezárásához. Az alkalmazásnak azonban továbbra is képesnek kell lennie kezelni az SQLConnect, az SQLDriverConnect és az SQLDisconnect SQL_STILL_EXECUTING visszatérési értékét.

Ha engedélyezve van a kapcsolatkészletezés, az SQLEndTran és az SQLSetConnectAttr támogatott az aszinkron műveletekhez.

Példák

A. Kapcsolati függvények aszinkron végrehajtásának engedélyezése

Az alábbi példa bemutatja, hogyan használható az SQLSetConnectAttr a kapcsolattal kapcsolatos függvények aszinkron végrehajtásának engedélyezésére.

BOOL AsyncConnect (SQLHANDLE hdbc)   
{  
   SQLRETURN r;  
   SQLHANDLE hdbc;  
  
   // Enable asynchronous execution of connection functions.  
   // This must be executed synchronously, that is r != SQL_STILL_EXECUTING  
   r = SQLSetConnectAttr(  
         hdbc,   
         SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE,  
         reinterpret_cast<SQLPOINTER> (SQL_ASYNC_DBC_ENABLE_ON),  
         0);  
   if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO)   
   {  
      return FALSE;  
   }  
  
   TCHAR szConnStrIn[256] = _T("DSN=AsyncDemo");  
  
   r = SQLDriverConnect(hdbc, NULL, (SQLTCHAR *) szConnStrIn, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);  
  
   if (r == SQL_ERROR)   
   {  
      // Use SQLGetDiagRec to process the error.  
      // If SQLState is HY114, the driver does not support asynchronous execution.  
      return FALSE;  
   }  
  
   while (r == SQL_STILL_EXECUTING)   
   {  
      // Do something else.  
  
      // Check for completion, with the same set of arguments.  
      r = SQLDriverConnect(hdbc, NULL, (SQLTCHAR *) szConnStrIn, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);  
   }  
  
   if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO)   
   {  
      return FALSE;  
   }  
  
   return TRUE;  
}  
  

B. Aszinkron véglegesítési műveletek

Ez a példa az aszinkron véglegesítési műveleteket mutatja be. A visszaállítási műveletek is így végezhetők el.

BOOL AsyncCommit ()   
{  
   SQLRETURN r;   
  
   // Assume that SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE is SQL_ASYNC_DBC_ENABLE_ON.  
  
   r = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT);  
   while (r == SQL_STILL_EXECUTING)   
   {  
      // Do something else.  
  
      // Check for completion with the same set of arguments.  
      r = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT);  
   }  
  
   if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO)   
   {  
      return FALSE;  
   }  
   return TRUE;  
}  

Lásd még:

Végrehajtási utasítások ODBC