Четверг Мая 17 , 2012
TEXT_SIZE
   


Выполнение пакетов командных запросов

Пытаясь с помощью ADO и SQL Server получить набор результатов, генерируемых хранимой процедурой, разработчики часто сталкиваются с одной проблемой. Если вы при помощи OLD DB-поставщика SQL Server вызвали хранимую процедуру SQL Server, которая перед запросом, возвращающим записи, выполняет командный запрос, ваш объект Recordset помечается как закрытый и он не содержит результаты запроса, возвращающего записи. Эта модель поведения обусловлена архитектурой. Закрытый объект Recordset соответствует командному запросу. Если точнее, он соответствует информационному сообщению<-n row(s) affected*, возвращаемому таким запросом. для перехода к результатам следующего запроса следует вызвать метод nextrecordset. кроме того, можно добавить в хранимую процедуру оператор set nocount on, подавляющий указанные сообщения; благодаря этому ado сразу же переходит к результатам первого запроса, возвращающего записи. подобная модель поведения не является отличительной чертой только хранимых процедур. похожая ситуация возникает и при выполнении пакетных запросов. рассмотрим пакетный запрос, использующий ado 2jc и классический visual basic: классический visual basic dim en as adodb.connection, rs as adodb.recordset dim strconn as string, strsql as string dim intrecordsaffected as integer strconn = "provider=sqloledb;data source=(local) etsdk;" & "initial catalog=northwind;trusted_connection=yes;set en = new adodb.connection en.open strconn strsql = "insert into customers ...;" & "select customerld, companyname from customers where ...;"&"update customers set companyname = ... where ...;" & "select customerld, companyname from customers where ...set rs = en.execute(strsql, intrecordsaffected, adcmdtext) do until rs is nothing debug.print "rs.state = " & rs.state & vbtab & "intrecordsaffected = " & intrecordsaffected set rs = rs.nextrecordset(intrecordsaffected) loop первоначально объект recordset закрыт, и переменная intrecordsaffected содержит значение 1. такие результаты соответствуют запросу insert, который не возвращает записей и изменяет одну запись бд. после того как мы вызовем метод nextrecordset, объект recordset становится открытым и содержит результаты первого запроса select. поскольку запрос select не изменяет каких-либо записей бд, переменная intrecordsaffected вернет -1. при повторном вызове метод 'nextrecordset вернет закрытый объект recordset, а значение переменной intrecordsaffected соответствует числу записей, затронутых запросом update. при следующем вызове метод nextrecordset возвращает результаты второго запроса select и задает переменной intrecordsaffected значение -1. при последнем вызове nextrecordset возвращает объект recordset, установленный в nothing, сообщая, что наборов результатов, ожидающих обработки, больше нет. ado.net обрабатывает этот же пакетный запрос иначе. команда разработчиков ado.net посчитала, что данная ситуация — одна из главных причин прострации разработчиков при использовании ado. они упростили процесс работы с пакетными запросами так, что теперь объект datareader автоматически перемещает вас к результатам первого запроса, возвращающего записи. полагаю, большинство разработчиков обрадуются такому изменению модели поведения. к сожалению, при этом пришлось поступиться частью функциональности. в результате изменения объект datareader не позволяет определить число записей, затронутых отдельными командными запросами. свойство recordsaffected объекта datareader — это текущее суммарное значение. думаю, лучше всего пояснить такое поведение на примере: visual basic .net dim strconn, strsql as string strconn = "provider=sqloledb;data source=(local) etsdk; " & "initial catalog=northwind;trusted_connection=yes;dim en as new oledbconnection(strconn) cn.open() strsql = "insert into customers ...;" & "select customerld, companyname from customers where ...;" & "update customers set companyname = ... where ,,.;" & "select customerld, companyname from customers where ...dim cmd as new oledbconnnand(strsql, en) dim rdr as oledbdatareader = cmd.executereader() do console.writelinef"recordsaffected = " & rdr.recordsaffected) do while rdr.read() console.writeline{vbtab & rdr.getname(0) & " - " & rdr.getvalue(0)) loop console. writeline() loop while rdr.nextresult() visual c# .net string strconn, strsql; strconn = "provider=sqloledb;data source=(local)\ etsdk; " + "initial catalog=northwind;trusted_connection=yes;"; oledbconnection en = new oledbconnection(strconn); cn.open(); strsql = "insert into customers . . . ; " + "select customerld, companyname from customers where ,..;" + "update customers set companyname = ... where . . . ; " + "select customerld, companyname from customers where ..."; oledbconwand cmd = new oleobcommand(strsql, en); oledbdatareader rdr = cmd. executereader(); do { console.writeline("recordsaffected = " + rdr.recordsaffected); while (rdr.read()) console.writeline("\t" + rdr.getname[0].tostring() + " - " + rdr.getvalue[0].tostring()); console.writeline(); } while (rdr.nextresult(); вы, возможно, заметили, что код ado.net похож на код ado. тем не менее результаты выполнения кода несколько отличаются. когда мы создаем объект datareader, вызывая метод executereader объекта command, datareader готов немедленно вернуть результаты первого запроса select. вызывая nextresult, мы переходим к результатам второго запроса select. при повторном вызове метод nexlresult возвращает false, поскольку запросов, возвращающих записи и ожидающих обработки, больше нет; как следствие, мы выходим из цикла. еще одно значительное изменение по сравнению с ado — поведение свойства recordsaffected объекта datareader, предположим, что запросы insert и update изменяют каждый по одной записи бд. свойство recordsaffected возвращает суммарное число записей, затронутых всеми командными запросами, предшествующими запросу, который возвращает записи и результаты которого в данный момент выбирает объект datareader. итак, когда метод executereader возвращает объект datareader, свойство recordsaffected последнего возвращает 1. при последующем вызове метода nextresult это свойство возвращает 2. помните, что не-dml командные запросы (например, create procedure и drор table) не изменяют записей и поэтому возвращают число затронутых записей как -1. если вам нужно при помощи ado.net определить число записей, затрагиваемых отдельными запросами, разделите пакет на отдельные запросы и выполняйте их поодиночке

Добавить комментарий


Защитный код
Обновить

Рейтинг пользователей: / 0
ХудшийЛучший 

Метео

Войти

Голосование

Идеальный вариант проведения новогодней корпоративной вечеринки - это…

Сейчас на сайте

Сейчас 7 гостей онлайн