OLE DB Provider / ADO / VB6

10 отговора 5 прегледа
#1

OLE DB Provider / ADO / VB6

Знае ли някой какво са направили юнаците от Microsoft, че всяка грешка с severity<11 предизвикват връщане на фиктивен Recordset при използване на SQL OLEDB Provider (MDAC 2.1; 2.5) без да се генерира грешка. При ODBC няма такъв проблем. За съжаление в MSDN-то не можах да намеря обяснение. Ще съм много благодарен, ако някой знае как да реша този проблем.
Отговор
в отговор на Zhivko #2

OLE DB Provider / ADO / VB6

Ne gi razbiram az takviz programistki raboti, no da te popitam vse pak ne6to drugo - Probval li si da sloji6 SP3 za VB-to i da vidi6 dali ne poravq ne6tata?
Отговор
в отговор на Zhivko #3

кое ODBC?

има бая промени, свързани със Severity<11 в ODBC for SQL Server 3.6. В общи линии, поведението му почва да се доближава до това на OLE DB-то. Така поне пише в MSDN.
Отговор
в отговор на Кромид #4

кажи все пак,

какво точно искаш да напраиш... може и да се сетя нещо.
Отговор
в отговор на Zhivko #5

За Кромид

Ами до сега си ползвах предимно OLDEDB for ODBC, но искам да използвам само OLEDB Provider. Проблема ми е следния: ако в процедурата (MSSQL7) се използва за целите на настройката Print или RaisError Severity<11 резултатите на процедурата се получават в n recordseta, като за всяка грешка се формира recordset; на всичкото отгоре, ако искам да си формирам съставна грешка при изпълнението на процедурата (т.е. на няколко места) Errors колекцията не се попълва с всички грешки, а само с първата ! SP3 на VStudio няма нищо общо с проблема за съжаление - проблема ми съществува си преди и след него. Допускам, че в типичния стил на изложение на MSDN-то тази особеност е спомената някъде на забутано място, верояно във връзка с нещо съвсем друго - но какво да се прави: и моята документация не е върхът. А ето и примерче, което илюстрира ефекта:
Отговор
в отговор на Zhivko #6

За Кромид - продължение

'We have MS SQL Server (SQLServer) and a Database (DB) with a 'stored procedure pr_FindCrnc: '------------------------------------------------------------------------------------------ 'if Exists (Select * From SysObjects Where Name = 'pr_FindCrnc') Drop Procedure pr_FindCrnc 'Go '------------------------------------------------------------------------------------------ 'Create Procedure pr_FindCrnc(@CrncKey Int) 'as '------------------------------------------------------------------------------------------ ' 'print '1' -- The problem ' 'Select * From Currency Where CrncKey = @CrncKey ' '------------------------------------------------------------------------------------------ 'Go 'Grant Execute On pr_FindCrnc To Public 'Go '------------------------------------------------------------------------------------------ ' 'When there is no row "print '1'" - evrything is OK ' 'But when there is "print '1'" - a multiple recordset are 'returned and the data are in the recordset N°i (N°2 in this case), 'while the other recordsets are closed ' 'The question is: 'What to do, for to make data to be received in the recordset N°1 'without changing the provider ("Provider=SQLOLEDB") ' Public Sub Main() Dim Con As New ADODB.Connection Dim Cmd As New ADODB.Command Dim RS As ADODB.Recordset Dim i As Long Con.CursorLocation = adUseClient Con.Open "Provider=SQLOLEDB;Data Source=SQLServer;Initial Catalog=DB;User ID=UserLogIn" Set Cmd.ActiveConnection = Con Cmd.CommandText = "pr_FindCrnc" Cmd.CommandType = adCmdStoredProc Cmd.Parameters("@CrncKey").Value = 2 Set RS = Cmd.Execute If (RS.State = adStateOpen) Then MsgBox "OK", vbInformation 'no row "print '1'" Else 'with row "print '1'" i = 1 'if somthing goes wrong then exit While While (RS.State <> adStateOpen) And (i < 1000) Set RS = RS.NextRecordset i = i + 1 Wend Debug.Assert (i < 1000) Debug.Assert (RS.State = adStateOpen) MsgBox "The data are in the recordset N°" & i & vbNewLine & vbNewLine & _ "What to do, for to make data to " & _ "be received in the recordset N°1 " & _ "without changing the provider (""Provider=SQLOLEDB"")", vbQuestion End If End Sub
Отговор
в отговор на Zhivko #7

За Кромид - продължение

мхм, прав си, не е в 1 топик... в общи линии, поне в 10-тина. и на едно забутано наистина място пише, че raisError със severity<11 е еквивалентно на Print. един вид, досегашното поведение на ODBC-то не е правилно. Все пак, коя версия на ODBC-то имаш? виж сега, това SP... абе, то си е напълно коректно и трябва наистина да връща два RecordSeta... точно толкова коректно, ако беше примерно така: Select 1 --(тва си е валиден statement в SQL Server...) Select * From Currency Where CrncKey = @CrncKey кво да ти кажа... аз лично използвам за всякакви цели severity 16. и да ти кажа и още нещо забутано - ако си успял да подкараш SQL-дебъгера, не се радвай много - черно на бяло си пише, че не работи с ADO (което пък, слава Богу, не е съвсем вярно - можеш да дебъгваш кажи-речи всичко, с изключение на процедури, в които бъзикаш Cursor-и). Така че аз, на твое място, разкарвам всички принтове и се пробвам с T-SQL Debuger-a. А специално това посмъртно не бих го направил на процедура. Мога да ти обясня защо, ако искаш, кажи.
Отговор
в отговор на Zhivko #8

За Кромид

Благодаря ти за мнението. Прав си като цяло относно коректността на синтаксиса ако тълкуваш Print и Select по един и същи начин. Но аз не съм съвсем съгласен - изрично (в ODBC) e предвидена възможност за успешно изпълнение с допълнителна информация - точно това са грешките с severity<11 и print.Не случайно се казва, че при при принт се получава запис в ADODB.Errors с SQLState=01000 + NativeError=0, т.е. хората са си предвидили нормална възможност за получаване на допълнителна информация. Подобна възможност и съществува при embeded SQL API и си работи съвсем новмално. Разбира се си остава ограничението, че ако искаш да се попълни колекцията, трябва да има поне една грешка със стойност на severity>=11. Аз лично съм склонен да мисля, че проблема е при мен, а не в Microsoft и нещо не съм установил както трябва в properties (доста са недокументирани!) Между другото, знаеш ли как може да се получават асинхронно диагностичните съобшения по време на асинхвонно изпълнение (не чрез select обаче)? Connection.Errors.Refresh не става за съжаление. За версиите на софтуера: ODBC for SQLSERVER 3.70.08.20 ODBC 3.520.4403.2 (MDAC 2.5 SDK) VStudio sp4 SQL Server 7.0 sp2 Колкото за SQLDebugera, в началото доста му се радвах, но постепенно поохладях към употребата му, защото в реална ситуация и при по-сложни процедури не върши многоработа. Просто като информация - примерно става дума за изчисляване на лихви по доста разнообразна система за олихвяване, отчитане на почивни дни и д.н. В началото си мислех да използвам OLE Automation object, но достъпа до сървъра е доста проблематичен и се отказах - това си е хубава технология, но само след като нещата се стабилизират (като задание). Ако имаш някои идеи относно настройка на SQL ще съм благодарен да ги споделиш.
Отговор
в отговор на Zhivko #9

диагностични съобщения

при асинхронна работа би трябвало да се получават на InfoMessage event-a на Connection object-a. примерно: dim withevents cn as Connection private sub cn_InfoMessage(ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, ByVal pConnection As ADODB.Connection) end sub малко идиотски параметри според мен (например pConnection-a, все едно че не знаеш кой connection ти е raise-нал event-a) но би трябвало да върши работа - не мога да го пробвам - нямам SQL Server в момента. за останалото - ще си помисля и ще ти кажа, ако се сетя.
Отговор
в отговор на Zhivko #10

диагностични съобщения

За съжаление не е точно така - и аз си мислех същото, но InfoEvent е само за допълнителни диагностични съобщения по време на осъществяване на connection. Даже, някой от последните грешки, които са коригирали с MDAC 2.1 sp2 са свързани точно с това - при асинхронно свързване не се получава допълнителна информация. Е не че е кой знае колко полезна при успешна връзка, но все пак: 1. Default database changed to ... 2. Default language changed to ... А за това, че ти подават pConnection не си прав - един и същи Event handler може да се използва с различни Connections object, което ти дава възможност да си манипулираш свободно оригиналния connection, без да се налага да се мисли чак толкоз много. Не че е кой знае каква, ама все пак ... напън. Имаше един сайт - Developers Exchange или нещо подобно, където бих могъл да ги питам за проблема си, но загубих адреса. Дали не знаеш нещо за този сайт?
Отговор
в отговор на Zhivko #11

идиотия...

ами, в общи линии, няма начин да се оправи ефекта с многото RecordSet-и. поразрових се и намерих някакво място, където се обсъждаше точно този проблем. и решението беше горе-долу това, което ти си написал - loop, докато дойде отворения RecordSet, евентуално показване на съобщението. кода беше делфийски, така че не е заради някаква странност на VB-то. какво да ти кажа - направи си една функция, която да ти връща първият отворен RecordSet... а Print е със severity 0 - това там изрично го пишеше.
Отговор