¼ò½é
ËùÓÐ SQL Server Êý¾Ý·ÃÎÊÓ¦ÓóÌÐò±à³Ì½Ó¿Ú (API) ¶¼ÌṩÁËÒ»¸ö³éÏóÀ´±íʾ»á»°ºÍ»á»°ÖеÄÇëÇó¡£SQL Server 2000 ÒÔ¼°¸üÔçµÄ°æ±¾ÏÞÖÆ±à³ÌÄ£ÐÍ£¬ËüÒªÇóÈκÎʱºòÒ»¸ö¸ø¶¨µÄ»á»°ÖÐ×î¶àÖ»ÄÜÓÐÒ»¸ö´ý¶¨µÄÇëÇó¡£Óм¸¸öÌæ´ú°ì·¨±»ÓÃÀ´½â¾öÕâÖÖÏÞÖÆ£¬ÔÚÕâÐ©Ìæ´ú°ì·¨ÖУ¬×î³£¼ûµÄ¿ÉÄܾÍÊÇ·þÎñÆ÷¶Ë¹â±ê¡£SQL Server 2005 ʵÏÖÁË Multiple Active Result Set (MARS)£¬Ëü½â³ýÁËÕâ¸öÔ¼Êø¡£±¾ÎĽéÉÜÁË MARS µÄÉè¼Æ¡¢½á¹¹ºÍÓïÒå±ä¸ü£¬ÒÔ¼°ÎªÁË´ÓÕâЩ¸Ä½øÖеõ½×î´óÊÕÒæ£¬Ó¦ÓóÌÐòÓ¦µ±×¢ÖØÊ²Ã´¡£
SQL Server 2000 Data Access Recap
Ŀǰ֧³ÖÓÃÓÚ¹¹½¨ SQL Server Ó¦ÓóÌÐòµÄÖ÷ÒªÊý¾Ý·ÃÎÊ API ÊÇ ODBC¡¢OLE-DB¡¢ADO ºÍ SqlClient .Net Provider¡£1ËüÃÇÈ«²¿¶¼Ìṩһ¸ö³éÏóÀ´±íʾһ¸öÖ¸Ïò·þÎñÆ÷µÄÒѽ¨Á¢Á¬½Ó£¬Í¬Ê±ÌṩÁíÍâÒ»¸ö³éÏóÀ´±íʾÔÚÕâ¸öÁ¬½ÓÖ®ÏÂÖ´ÐеÄÇëÇó¡£ÀýÈ磬SqlClient ʹÓà SqlConnection ºÍ SqlCommand ¶ÔÏ󣬶ø ODBC ÔòʹÓà SQL_HANDLE_DBC ÀàÐÍºÍ SQL_HANDLE_STMT ÀàÐ͵ľä±ú¡£
ËùÓз¢Ë͸ø SQL Server µÄÖ´ÐÐÇëÇó¶¼ÊǼ¸ºõÒÔÏÂÁ½ÖÖÐÎʽ֮һ£º1) Ò»×é T-SQL Óï¾ä£¬Í¨³£Ò²³ÆÎªÅú´¦Àí£¬»òÕß 2) ´æ´¢¹ý³Ì»òº¯ÊýµÄÃû³Æ£¬¼ÓÉϲÎÊýÖµ£¨¼ÙÈçºÏÊÊ£©¡£Çë×¢ÖØ£¬Ìá½»Ò»¸ö SELECT »ò DML Óï¾ä¸ø·þÎñÆ÷ÊÇÒ»¸öµ¥Óï¾äÅú´¦Àí£¬ÕâÊǵÚÒ»ÀàÇëÇóµÄÌØÀý¡£
ÔÚÈκÎÒ»ÖÖÇé¿öÏ£¬SQL Server ¶¼»áÖØÉêÅú´¦Àí»ò´æ´¢¹ý³ÌÖаüº¬µÄÓï¾ä£¬È»ºóÖ´ÐÐÕâЩÓï¾ä¡£Óï¾ä¿ÉÄÜ»áÉú³É½á¹û£¬Ò²¿ÉÄܲ»Éú³É½á¹û£¬²¢ÇÒÓï¾ä¿ÉÄÜ»áÏòµ÷ÓÃÕß·µ»Ø¸½¼ÓÐÅÏ¢£¬Ò²¿ÉÄܲ»·µ»Ø¡£
½á¹ûÖ÷ÒªÊÇÓÉ SELECT ºÍ FETCH Éú³ÉµÄ¡£SQL Server ͨ¹ý½«½á¹û·µ»Ø¸øµ÷ÓÃÕßÀ´Ö´ÐÐ SELECT Óï¾ä¡£ÕâÒâζ×Å£¬ÔÚ²éѯִÐÐÒýÇæ²úÉúÐеÄͬʱ£¬ÕâЩÐлᱻдÈëÍøÂç¡£¸üÈ·ÇеØËµ£¬Ëù²úÉúµÄÕâЩÐлᱻ¸´ÖƵ½Ô¤Ïȱ£ÁôµÄÍøÂ绺³åÇøÖУ¬È»ºó»º³åÇø»á±»·µ»Ø¸øµ÷ÓÃÕß¡£ÍøÂçдÈë²Ù×÷»á³É¹¦£¬²¢ÔÚ¿Í»§¶ËÇý¶¯³ÌÐò´ÓÍøÂçÖжÁȡʱÊÍ·ÅÒÑÓùýµÄ»º³åÇø¡£¼ÙÈç¿Í»§¶ËûÓÐÏûºÄ½á¹û£¬ÔÚÏàͬµãÉϵÄÍøÂçдÈë²Ù×÷½«»á±»×èÖ¹£¬·þÎñÆ÷ÖеÄÍøÂ绺³åÇø½«»á±»ÌîÂú£¬Ö´Ðоͻᱻ¹ÒÆð£¬µÈ´ý״̬ºÍÖ´ÐÐỊ̈߳¬Ö±µ½¿Í»§¶ËÇý¶¯³ÌÐò²¶×½¶ÁÈ¡¡£ÕâÖÖ²úÉú½á¹ûºÍ¼ìË÷½á¹ûµÄģʽͨ³£±»³ÆÎª¡°Ä¬ÈϽá¹û¼¯¡±£¬¸üÕýʽµÄÃû³ÆÔòÊÇ¡°Á÷Ë®Óαꡱ¡£
¸½¼ÓÐÅÏ¢Ò²¿ÉÄÜÒÔÆäËû·½Ê½£¨¿ÉÄÜûÓнá¹û·µ»Ø·½Ê½ÄÇôÃ÷ÏÔ£©±»·µ»Ø¸øµ÷ÓÃÕß¡£ÕâÖÖÇé¿ö°üÀ¨´íÎó¡¢¾¯¸æºÍÐÅÏ¢ÐÔÏûÏ¢¡£ËüÃÇ»òÕßͨ¹ý PRINT ºÍ RAISERROR Óï¾äÏÔʽ·µ»Ø£¬»òÕßͨ¹ýÓï¾äÖ´ÐÐÆÚ¼ä²úÉúµÄ¾¯¸æºÍ´íÎóÒþʽ·µ»Ø¡£Í¬ÑùµØ£¬µ± NOCOUNT ÉèÖÃÑ¡Ïî±»ÉèÖÃΪ OFF ʱ£¬SQL Server »á¶Ôÿ¸öÒÑÖ´ÐеÄÓï¾ä·¢ËÍÒ»¸ö¡°done row count¡±±ê¼Ç¡£ÕâÖÖ¸½¼ÓÐÅÏ¢Ò²¿ÉÄܵ¼ÖÂÍøÂçдÈ뻺³åÇø±»ÌîÂúºÍÖ´Ðб»¹ÒÆð¡£
ÕâÖÖ±³¾°Ê¹ÎÒÃÇ¿ÉÒÔÀí½â SQL Server 2000 ÒÔ¼°¸üÔç°æ±¾ÔÚÖ§³ÖÿÁ¬½Ó¶à¸ö´ý¶¨ÇëÇóʱµÄһЩ±à³ÌÄ£ÐÍÏÞÖÆ¡£
¡°Á¬½Ó·±Ã¦¡±
¶ÔÓÚ±¾ÎÄÖеÄʾÀý£¬ÎÒÃǽ«¼Ù¶¨ÒÔÏÂÕâÑùÒ»¸ö¼òµ¥µÄÇé¾³£ºÒ»¸öËÉÉ¢Á¬½ÓµÄÇåµ¥´¦ÀíϵͳʹÓá°Operations¡±±í×÷Ϊ¶ÓÁÐÀ´½ÓÊÕÀ´×ÔÆäËû×é¼þµÄÇëÇó£º
OPERATIONS
ÒÑ´¦Àí
λ
operation_id
int
Ö÷¼ü
operation_code
char(1)
'D' ¨C decrease inventory
'I' ¨C increase inventory
'R' ¨C reserve inventory
product_id
uniqueidentifier
ÊýÁ¿
bigint
ÎÒÃǼٶ¨Õâ¸ö×é¼þÖÎÀí×Ų»Í¬²úÆ·Ïߺ͹©¸øÉ̵ÄÇåµ¥£¬¶ø product_id ÔòÈ·¶¨ÒªÊ¹ÓÃÄĸö·þÎñÆ÷ºÍÊý¾Ý¿âÒÔ¼°ÈçºÎÖ´ÐÐÇëÇóµÄ²Ù×÷¡££¨Ò²¾ÍÊÇ˵£¬¼Ù¶¨²»¿ÉÄÜдÈëһЩ³É×é²Ù×÷À´´¦Àí¶ÓÁÐÖеÄËùÓÐÇëÇ󣩡£
Õâ¸ö×é¼þÔÚÒ»¸ö²åÈëµ½±íÖеÄËÉÉ¢´¦ÀíÇëÇóÖпªÊ¼ÔËÐУ¬²¢Ôڳɹ¦Íê³ÉÖ¸¶¨²Ù×÷ʱ½«ÕâЩÇëÇó±ê¼ÇΪÒÑ´¦Àí¡£
α´úÂëÀàËÆÈçÏÂËùʾ£º
while (1){Get all messages currently available in Operations table;For each message retrieved{ProcessMessage();Mark the message as processed;}}Ç°ÃæÒ»¸öʹÓà odbc µÄ·½·¨ÀàËÆÈçÏÂËùʾ£¨ºöÂÔÁËһЩϸ½ÚºÍ´íÎó´¦Àí£©£º
SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1);SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt2);while (true){ SQLExecDirect(hstmt1, (SQLTCHAR*)"select operation_id, operation_code, product_id, quantity from dbo.operations where processed=0", SQL_NTS); while (SQL_ERROR!=SQLFetch(hstmt1)) {ProcessOperation(hstmt1);SQLPrepare(hstmt2, (SQLTCHAR*)"update dbo.operations set processed=1 where operation_id=?", SQL_NTS);SQLBindParameter(hstmt2, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &opid, 0, 0);SQLExecute(hstmt2); }}µ«ÊÇ£¬³¢ÊÔÖ´ÐÐ hstmt2 »áµ¼Ö£º
[Microsoft][ODBC SQL Server Driver]Connection is busy with results for another hstmt.
ʹÓà SqlClient дÈëµ½ Microsoft Visual C# ÖеÄÏàͬÂß¼ÀàËÆÈçÏÂËùʾ£º
SqlCommand cmd = conn.CreateCommand();SqlCommand cmd2 = conn.CreateCommand();cmd.CommandText= "select operation_id, operation_code, product_id, quantity from dbo.operations where processed=0";cmd2.CommandText="update dbo.operations set processed=1 where operation_id=@operation_id";SqlParameter opid=cmd2.Parameters.Add("@operation_id", SqlDbType.Int);reader=cmd.ExecuteReader();while (reader.Read()){ ProcessOperation(); opid.Value=reader.GetInt32(0); // operation_id cmd2.ExecuteNonQuery();}ͬÑùµØ£¬³¢ÊÔÖ´ÐдËÂß¼»áµ¼Ö£º
InvalidOperationException, There is already an open DataReader associated with this Connection which must be closed first.
ÕâЩ´íÎóÊÇȱÉÙ MARS µÄ×îÖ±½Ó֤ʵ£»ÔÚÈκÎʱºò£¬Ò»¸ö¸ø¶¨µÄ SQL Server Á¬½ÓÖ®ÏÂ×î¶àÖ»ÄÜÓÐÒ»¸ö´ý¶¨ÇëÇó¡£
ÎÒÓÐÒâºöÂÔÁË OLEDB£¬ÒòΪËü»á²úÉúÂÔ΢Óе㲻ͬµÄÐÐΪ¡£
SQL Server 2005 ÖÐµÄ Multiple Active Result Set (MARS)(1)À´×ÔÍøÂ磬½ö¹©²Î¿¼¡£
