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-Code:
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-Code:
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:
http://go.microsoft.com/fwlink/?LinkId=110393
Project1.dpr
Delphi-Quellcode:
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Unit1.dfm
Delphi-Quellcode:
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
Delphi-Quellcode:
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
{ Private-Deklarationen }
public
{ Public-Deklarationen }
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!