Hi,
ich arbeite grade an der Kompatibilität meiner Software zu SQL Server 2008.
Leider habe ich damit massive Probleme....
Ich vermute stark, dass das Problem mit dem Native Client 10 zusammen hängt.
Hier mein Problem:
Ich rufe in einer
Transaktion eine
StoredProcedure (über TADOStoredProc) auf.
Danach ändere ich in meiner StoredProcedure Komponente den 'ProcedureName' und
Refreshe die Parameter.
Beim nächsten ausführen über "ExecProc" in einer Transaktion bekomme ich folgenden Fehler:
Falsche Syntax in der Nähe des 'set'-Schlüsselworts.
Weitere Fakten:
Dieser Fehler taucht teilweise auch bei Insert Anweisungen auf.
Ohne Transaktionen gibt es kein Problem.
Mit dem Native Client 9 funktioniert es mit oder ohne Transaktionen.
Hier der SQL Code der auf dem SQL Server ankommt:
SQL Log - native client 10 - mit Transaktion
SQL-Anweisung
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| exec [master].[sys].sp_procedure_params_100_rowset N'test',1,NULL,NULL go exec [test] go exec [master].[sys].sp_procedure_params_100_rowset N'test',1,NULL,NULL go SET NO_BROWSETABLE ON go set fmtonly on EXEC set fmtonly off -- Exception in Delphi here go set fmtonly off go |
Und jetzt was ohne Transaction oder mit/ohne Transaktion bei Native Client 9 ankommt:
SQL-Anweisung
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| exec [master].[sys].sp_procedure_params_100_rowset N'test',1,NULL,NULL go exec [test] go exec [master].[sys].sp_procedure_params_100_rowset N'test',1,NULL,NULL go SET NO_BROWSETABLE ON go set fmtonly on EXEC set fmtonly off go set fmtonly off go SET NO_BROWSETABLE OFF go exec [test] go |
Die Stelle mit dem Problem ist
set fmtonly on EXEC set fmtonly off
Ich vermute dass der Native client 10 in der Transaktion aus versehen eine Exception auslöst. Bei allen anderen varianten ist der abgesendete Code der gleiche (also genau so falsch), löst aber keinen Fehler aus.
Ich habe schon alle möglichen Property-Kombinationen der AdoConnection und AdoStoredProcedure Komponente getestet. Leider ohne Erfolg.
Ein Workaround war KEIN Parameters.Refresh zu machen, sondern die Parameter zu clearen und dann manuell anzulegen.
Leider gab es dann bei diversen anderen stellen Problemen mit Insert anweisungen.
Hier eine Demo:
Um das Problem reproduzieren zu können, benötigt Ihr den Native Client 10:
go.microsoft.com/fwlink/?LinkId=110393
Project1.dpr
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| program Project1;
uses Forms, Unit1 in 'Unit1.pas' ;
{$R *.res}
begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. |
Unit1.dfm
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100:
| object Form1: TForm1 Left = 424 Top = 528 Width = 483 Height = 187 Caption = 'Form1' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OldCreateOrder = False Position = poScreenCenter OnDestroy = FormDestroy DesignSize = ( 475 153) PixelsPerInch = 96 TextHeight = 13 object Button1: TButton Left = 8 Top = 56 Width = 233 Height = 25 Caption = 'connect to DB and create StoredProc' TabOrder = 0 OnClick = Button1Click end object Button2: TButton Left = 8 Top = 120 Width = 201 Height = 25 Caption = 'Execute StoredProc' TabOrder = 1 OnClick = Button2Click end object CheckBox1: TCheckBox Left = 8 Top = 104 Width = 193 Height = 17 Caption = 'use transactions' Checked = True State = cbChecked TabOrder = 2 end object LabeledEdit1: TLabeledEdit Left = 8 Top = 24 Width = 378 Height = 21 Anchors = [akLeft, akTop, akRight] EditLabel.Width = 81 EditLabel.Height = 13 EditLabel.Caption = 'ConnectionString' TabOrder = 3 Text = 'Provider=SQLNCLI10.1' end object Button3: TButton Left = 393 Top = 22 Width = 75 Height = 25 Anchors = [akTop, akRight] Caption = 'build' TabOrder = 4 OnClick = Button3Click end object Button4: TButton Left = 393 Top = 119 Width = 75 Height = 25 Anchors = [akRight, akBottom] Caption = 'Close' TabOrder = 5 OnClick = Button4Click end object ADOConnection1: TADOConnection ConnectionString = 'Provider=SQLNCLI10.1' LoginPrompt = False Provider = 'SQLNCLI10.1' Left = 104 Top = 48 end object ADOStoredProc1: TADOStoredProc Connection = ADOConnection1 Parameters = <> Left = 200 Top = 48 end object ADOCommand1: TADOCommand Connection = ADOConnection1 Parameters = <> Left = 280 Top = 56 end end |
Unit1.pas
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DB, ADODB, StdCtrls, ExtCtrls;
type TForm1 = class(TForm) ADOConnection1: TADOConnection; ADOStoredProc1: TADOStoredProc; Button1: TButton; Button2: TButton; CheckBox1: TCheckBox; LabeledEdit1: TLabeledEdit; Button3: TButton; Button4: TButton; ADOCommand1: TADOCommand; procedure Button1Click(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); private public end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); begin ADOConnection1.connected := false; ADOConnection1.ConnectionString := LabeledEdit1.Text; ADOConnection1.connected := true;
try ADOCommand1.CommandText := 'CREATE PROCEDURE [test] AS'; ADOCommand1.Execute; except end; end;
procedure TForm1.FormDestroy(Sender: TObject); begin if ADOConnection1.Connected then begin
ADOCommand1.CommandText := 'IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N''[test]'') AND type in (N''P'', N''PC'')) DROP PROCEDURE [test]'; ADOCommand1.Execute;
ADOConnection1.connected := false;
end; end;
procedure TForm1.Button2Click(Sender: TObject); begin if CheckBox1.Checked then ADOConnection1.BeginTrans; try ADOStoredProc1.ProcedureName := '[test]'; ADOStoredProc1.parameters.Refresh; ADOStoredProc1.ExecProc;
if CheckBox1.Checked then ADOConnection1.CommitTrans; except on E: Exception do begin if CheckBox1.Checked and ADOConnection1.InTransaction then ADOConnection1.RollbackTrans;
ShowException(E, e); end; end; end;
procedure TForm1.Button3Click(Sender: TObject); begin LabeledEdit1.Text := PromptDataSource(Handle, LabeledEdit1.Text); end;
procedure TForm1.Button4Click(Sender: TObject); begin close; end;
end. |
Nach starten der Applikation müsst Ihr den Connectionstring angeben. Klick auf 'build'
ACHTUNG: Der Native Client 10 hat wohl noch ein paar Probleme bei der SQL Authentifizierung (User/Pass Anmeldung). Entweder folgende Anleitung verwenden oder folgenden ConnectionString manuell anpassen und in das Eingabefeld einfügen
1. Provider auswählen -> weiter.
2. Bei "1." die IP oder den Servernamen angeben.
3. Bei "2." "Use an specific user name an password" auswählen.
4. "User name:" angeben (meist 'sa').
5. Bei "Blank password" den Haken entfernen.
6. Bei "Allow saving password" den Haken setzen.
7. "Password:" angeben.
8. Bei "3." Die Datenbank auswählen.
9. Verbindung Testen, dann weiter auf Tab "Alle"
10. Doppelklick auf Eintrag "Integrated Security". Dann ohne Änderung auf "OK".
11. Doppelklick auf Eintrag "Persist Security Info". Eigenschaftswert auf "True" ändern.
12. Dialog mit "OK" verlassen.
Beispiel ConnectionString:
Provider=SQLNCLI10.1;Password=<PASSWORT>;Persist Security Info=True;User ID=sa;Initial Catalog=<DATENBANK>;Data Source=<SERVERADRESSE>;Initial File Name="";Server SPN=""
Es wird automatisch eine StoredProcedure angelegt und beim Beenden wieder entfernt.
Für eure Hilfe wäre ich sehr dankbar!