Autor Beitrag
ManniTwo
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 46

Win XP SP III, Ubuntu 8.04, Debian 5.0
Delphi 5 Pro; Delphi 2005; C++,C# (VS 2005); Java, Ruby (Eclipse)
BeitragVerfasst: Fr 10.07.09 10:57 
Hallo Leute,

ich verwende die ADO-Komponenten (nicht-visuell sondern per Instanziierung im Source für eine Konsolenanwendung) TADOConnection und TADOCommand, um auf eine SQL Server Compact Edition Datenbank (Version 3.5) aus Delphi 2005 heraus zuzugreifen.

Nach meinem ersten Test der Machbarkeit mit "einfachen SQL-Strings", möchte ich nun auf parametrisierte Abfragen umstellen, damit ich später mehrere Inserts mit wechselnden Parameter-Werten (halbwegs) performant ausführen kann.

Der Zugriff klappt grundsätzlich auch ganz wunderbar und auch bei der Verwendung von einem einzigen Parameter läuft alles ordentlich durch.

Mein Problem:
Wenn ich mehrere Parameter verwende, stürzt die Anwendung ab (ich kann keine Exception fangen, auch nicht bei schrittweisem Debuggen).

Hier ein Minimalbeispiel:
Die Testdatenbank besteht nur aus einer einzigen, einfachen Tabelle, die mit folgendem Statement erzeugt wurde:
ausblenden SQL-Anweisung
1:
CREATE TABLE ZweiParameterTest (feld1 nvarchar(100), feld2 nvarchar(100))					

Und hier meine Funktion:
ausblenden volle Höhe Delphi-Quelltext
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:
procedure InsertThingsIntoDatabase;
var
  adoConn: TADOConnection;
  adoCmd: TADOCommand;
  i: Integer;
begin
  try
    try
      adoConn := TADOConnection.Create(nil);
      adoConn.ConnectionString := 'Provider=Microsoft.SQLSERVER.CE.OLEDB.3.5;Data Source="X:\test.sdf";';

      adoConn.Open;

      adoCmd := TADOCommand.Create(nil);
      adoCmd.Connection := adoConn;

      // Mit nachfolgender Zeile funktionierts, wenn man unten dann nur einen Parameter setzt.
      // adoCmd.CommandText := 'INSERT INTO ZweiParameterTest (feld1) VALUES (:feld1);';

      adoCmd.CommandText := 'INSERT INTO ZweiParameterTest (feld1, feld2) VALUES (:feld1, :feld2);';

      adoCmd.Prepared := true;

      adoCmd.Parameters[0].Value := 'Test';
      adoCmd.Parameters[1].Value := 'Test';
      
      adoCmd.Execute; // Diese Anweisung kehrt nicht zurück und lässt das Prog abstürzen.

    except
      // Ein bisschen Error-Handling, Logging und so. Wird leider nie erreicht.
      end;
  finally
    adoConn.Close;
    adoCmd.Free;
    adoConn.Free;
    end;
end;


Das habe ich schon erfolglos probiert:

  • ADOQuery statt ADOCommand
  • Verwendung von Parametern über "?" oder "@paramName"
  • Andere Datentypen statt nvarchar
  • Setzen von adoCmd.ParamCheck := false
  • Parameter per Namen und nicht per Index ansprechen.
  • Explizites Setzen des "DataType" der TParameter-Objekte.
  • Bei Verwendung einer MySQL-Datenbank funktioniert der Code


Vielleicht erkennt ja jemand, was ich falsch mache oder was ich noch probieren könnte.
Vielen Dank.

[CHANGELOG]
13.07.09: Liste erfolgloser Versuche erweitert nach Ideen von bummi und Critter
13.07.09: Zu Testzwecken MySQL-Datenbank verwendet. Damit geht es. hmmm...
[/CHANGELOG]

_________________
Wer andern eine Bratwurst brät, der hat ein Bratwurst-Brat-Gerät, oder anders:
ausblenden Delphi-Quelltext
1:
if Self.BraetAndernEineBratwurst then Self.HasBratwurstBratGeraet := true;					


Zuletzt bearbeitet von ManniTwo am Mo 13.07.09 16:28, insgesamt 2-mal bearbeitet
Critter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 328
Erhaltene Danke: 3

Windows 7
Delphi 7 Pro.
BeitragVerfasst: Fr 10.07.09 14:58 
Hallo,

die ersten Beiden Ideen die ich da habe ist 1. versuchen den Wert Getypt also nicht über das Variante .Value zu zu weisen und 2. die Parameter per Namen und nicht per Index an zu sprechen.

Also so:
ausblenden Delphi-Quelltext
1:
2:
  adoCmd.ParamByName['Feld1'].AsString := 'Test';
  adoCmd.ParamByName['Feld2'].AsString := 'Test';


Keine Ahnung ob das hilft aber versuchen kann man es ja mal ;).

_________________
Diejenigen, die grundlegende Freiheiten aufgeben, um ein wenig mehr vorrübergehende Sicherheit zu erkaufen, verdienen weder Freiheit noch Sicherheit.
(Benjamin Franklin;"The Papers of Benjamin Franklin", Vol. 6, Apr. 1, 1755, through Sep. 30, 1756)
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Fr 10.07.09 16:01 
adoCmd.Parameters[0].DataType:=ftString;
ManniTwo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 46

Win XP SP III, Ubuntu 8.04, Debian 5.0
Delphi 5 Pro; Delphi 2005; C++,C# (VS 2005); Java, Ruby (Eclipse)
BeitragVerfasst: Mo 13.07.09 09:23 
Erst einmal Danke für Eure Antworten. Leider war das noch nicht zielführend.

user profile iconCritter hat folgendes geschrieben Zum zitierten Posting springen:

1. versuchen den Wert Getypt also nicht über das Variante .Value zu zu weisen

--> Die TParameter-Klasse, die ich hier habe (Unit ADODB, die bei Delphi 2005 mit dabei ist), hat keine AsString-Operation.

user profile iconCritter hat folgendes geschrieben Zum zitierten Posting springen:

2. die Parameter per Namen und nicht per Index an zu sprechen.

--> Das macht keinen Unterschied, habe ich getestet.

user profile iconbummi hat folgendes geschrieben Zum zitierten Posting springen:
adoCmd.Parameters[0].DataType:=ftString;

--> Der DataType wird automatisch erkannt (wahrscheinlich weil das Statement ja vorkompiliert wird) und auf ftWideString gesetzt. Explizites Setzen auf ftString führt zur Ausnahme: "Der angegebene Typname wurde nicht erkannt. Wie ich bereits geschrieben habe, habe ich auch andere Datentypen probiert, dann wird beispielsweise der DataType automatisch auf ftInteger gesetzt, der Effekt ist aber am Ende der gleiche.

_________________
Wer andern eine Bratwurst brät, der hat ein Bratwurst-Brat-Gerät, oder anders:
ausblenden Delphi-Quelltext
1:
if Self.BraetAndernEineBratwurst then Self.HasBratwurstBratGeraet := true;					
ManniTwo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 46

Win XP SP III, Ubuntu 8.04, Debian 5.0
Delphi 5 Pro; Delphi 2005; C++,C# (VS 2005); Java, Ruby (Eclipse)
BeitragVerfasst: Mi 15.07.09 10:52 
Ich erlaube mir mal ein Schiebeposting, die 24h-Begrenzung ist ja eingehalten.

Wäre super, wenn noch einmal jemand einen Blick drauf wirft oder es vielleicht bei sich ausprobiert.

Habe jetzt bei uns im Team kommuniziert, dass Delphi/Win32 dieses mal (ausnahmsweise) nicht die geeignete Entwicklungstechnik ist und C# empfohlen. Mit den dort vorhandenen Bibliotheken zum Zugriff auf SqlCE-Datenbanken ist man sowieso um einiges schneller als mit ADO. Die Umsetzung in C# wird nun also beraten.

Trotzdem wüsste ich gern, ob ich da einfach falsch programmiert habe oder SQL Server Compact über ADO-Zugriff mehrere Parameter einfach nicht unterstützt.

_________________
Wer andern eine Bratwurst brät, der hat ein Bratwurst-Brat-Gerät, oder anders:
ausblenden Delphi-Quelltext
1:
if Self.BraetAndernEineBratwurst then Self.HasBratwurstBratGeraet := true;					
spidergen
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Do 13.08.09 14:26 
Hallo,

hab das gleiche Problem mit mehrfachen Parametern. Allerdings unter C++. Gibt es schon irgendwelche weiteren Erkenntnisse?
spidergen
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Fr 14.08.09 09:30 
Hab noch was rausgefunden:

Das Problem tritt bei mir nur bei SQL Server Compact MIT SP1 auf. Verwende ich den SQL Server Compact OHNE SP1, so lassen sich queries mit mehreren Parametern ohne weiteres ausführen.