Autor Beitrag
Tana´Ri
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 230



BeitragVerfasst: Di 25.03.03 11:54 
Hi,

so sieht zur zeit meine attach procedure aus:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
if not dataset.Active then dataset.Open;
if (dataset.CanModify) then
 try
    dataset.Append;
    dataset.FieldValues['KontaktVorname']:=getPCName+' '+inttoStr(counter);
    dataset.FieldValues['KontaktNachname']:='ID_'+inttostr(ThreadID);
    dataset.Post;

 except
  dataset.UpdateAction(TBasicAction(uaRetry)); // siehe *
  if dataset.Active then dataset.Close;
 end;


nun ich erzeuge mehrere Instanzen und lasse diese auf die datenbank (Access 2000) zugreifen bzw. schreiben. ich habe ein thread erstellt, von dem ich in meinem Form mehrere Instanzen erzeuge. Diese Tragen nur daten ein, nach undefinierbare Zeit kommt es zu einem Fehler, die Meldung lautet das auf aktuellen datensatz nicht zugegriffen werden kann da dieser zur zeit gesperrt sei, dadurch gehen datensätze verloren, da diese dann nicht eingetragen werden. Append bedeutet doch normal anhängen der daten, wie kann da ein datensatz gesperrt sein ???

HILFE !!! dieses Problem ärgert mich schon ne geraume zeit ich hoffe hier kann mir mal einer helfen.

* dies soll bei fehler die aktion erneut starten besser wäre natürlich ein preventives mittel.

ps: wichtig wäre vielleicht anzumerken das ich kein TADOConnection oder Command oder Table oder Query benutze, ich nutze nur das DataSet Objekt (genau: TBetterADODataSet 4.02)
Provider Jet Engine 4.0
Access 2000
Platform Win2k Sp3
MDAC 2.6

_________________
mfg
Tana´Ri
MSCH
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1448
Erhaltene Danke: 3

W7 64
XE2, SQL, DevExpress, DevArt, Oracle, SQLServer
BeitragVerfasst: Di 25.03.03 18:57 
Ich hab das das auch mal gehabt; vieleicht hilfts dir, setzte im Objektinspektor den Cursor auf Server. Wenn du mehrere Threads am laufen hast, kriegst du eh Probleme mit dem ganzen Synchronisieren, deine Fehlermeldung spricht dafür, dass zwei Funktionen gleichzeitig auf ein und denselben Datensatz zugreifen. Was spricht dagegen das via sql mit insert zu machen?
grez
msch
Tana´Ri Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 230



BeitragVerfasst: Mi 26.03.03 08:47 
hi MSCH,

so sieht meine Standardkonfiguration aus:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure Thr_BADODataset.SetStandardConfig;
 begin
   if dataset.Active then dataset.close;
    with DataSet do
     begin
      CursorLocation:=clUseServer; // ist schon auf Server gesetzt 
      CursorType:=ctkeyset;
      CommandType:=cmdTableDirect;
      LockType:=ltPessimistic;
      CommandText:='Tablename';
    end;{with}
   if not dataset.Active then dataset.Open;
end;

wieso nicht SQL ? Nun ich habe auch eine Variante mit Sql gebastelt, eigentlich bin ja gerade dabei alles mal zu testen und verschiedene Wege zu versuchen. Ich habe gelesen das diese Problematik, also meine, durch das AutoIncFeld in meiner Access-Datenbank bedingt sei. In wiefern oder sogar einen Lösungvorschlag habe ich diesbezüglich noch nicht gefunden.

Ich habe das Ganze in als ein Thread erstellt sodas ich eine MultiUserUmgebung simulieren kann, im Form erzeuge ich einfach soviele ich will, aber nur weil 'User' gleichzeitig in die Datenbank schreiben wollen, darf dies in einer ordenlichen Anwendung nicht passieren, ich hoffe du verstehst was ich meine.

Später sollen Daten natürlich nicht nur per Append in die Datenbank gelangen, nein auch Edit, insert, sql ... alles sollte funktionieren und das fehlerfrei. Ich denke, wenn es mir gelingt diesen Fehler hier in den Griff zubekommen so mag er auch bei den anderen Variationen des Datenzugriffs keine Rolle mehr spielen.
Vielleicht kommt dann noch ein Problem dazu, denn ich muss anschließend die Stabilität noch in real-lan testen, d.h. wenn wirklich mehrere PC´s auf die Datenbank (Access-Tabelle) zugreifen. Ich hatte das sogar mal kurz getestet, dabei hat es mir irgendwie die Datenbank zersört, musste immer reparieren (dies könnte allerdings am selben Üroblem liegen)

thx MSCH

_________________
mfg
Tana´Ri
Tana´Ri Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 230



BeitragVerfasst: Do 27.03.03 10:13 
Titel: allgemeines ADO Probleme ?
Hi leute,

solangsam gehen mir die Ideen aus, ich weiss nicht was an dem Code falsch ist, jedenfalls ob ich nun mit dem ADO- Dataset oder mit dem Command oder Query benutze, immer bekomme ich diesen aktualisierungs fehler wegen der sperre.

In der ATTACH Procedure habe ich diese verschiedenen Verfahren ausprobiert und nix wirkt :evil:
Im Moment steht im Code noch die version mit query, ich poste hier mal meine gesammten code des testprogramms. Es mag wohl unschönheiten beinhalten .... aber vielleicht hilfts.
Mein Programm läuft auf local C: und mein Tabelle liegt im lan auf einem anderen rechner K:
Grob nochmal das Prob:" Mehrfachzugriff "
(wenn ich nur eine Instanz habe funktioniert es [alles])

*es mag sein das einiges unbekannt sei (units), oder ander dinge sind ausgeklammert .. das sollte jedoch nicht vom wesentlichen ablenken (hinsichtlich ADO irrelevant)
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:
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:
106:
107:
108:
109:
// Das Form 
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Contnrs,
  Dialogs, DB, ADODB, BetterADODataSet, StdCtrls, Mask, DBCtrls,thr_betteradodataset,
  TCIDebug_101, DBClient;

type
  Te = class(TForm)
    Label1: TLabel;
    ComboBox1: TComboBox;
    Memo1: TMemo;
    Label2: TLabel;
    Label3: TLabel;
    ADOQuery1: TADOQuery;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    Better_ADO_DataSet      : Thr_BADODataset;
    ObjList,objlistDebugWin : TObjectlist;
    winbool:boolean;

    //win : TDebugWin;
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;


const
  NUMBER_OF_THRBETTERADODATASET = 10;   

var
  Form1 : Te;

implementation

{$R *.dfm}

//----------------------------------------------------------------------------//

procedure Te.FormCreate(Sender: TObject);
var j,i:integer;
    filename:string;
    fwork : ComboArray;
 begin
 {if messagedlg('Soll zu jedem Thread ein DebugWin angezeigt werden?',mtCustom,[mbyes,mbno],0)=mryes then
  winbool:=true else winbool:=false;}

  ObjList := TObjectlist.Create(false);
  objlistDebugWin := TObjectlist.Create(True);
  {if not winbool then
   begin
    win:=tdebugwin.Create(self);
    objlistDebugWin.add(win);
    win.Show;
  end;}

  for i:=1 to NUMBER_OF_THRBETTERADODATASET do
   begin
   { if winbool then begin 
     win:=tdebugwin.Create(self);
     objlistDebugWin.add(win);
     win.Show;                                               
    end;}

    for j:=0 to 3 do fwork[j]:=A;
    {case random(5) of
     0 : fwork[j]:=A;
     1 : fwork[j]:=R;
     2 : fwork[j]:=W;
     3 : fwork[j]:=SQL;
     4 : fwork[j]:=Nothing;
    end;}

    filename:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source=K:\DBSFOLDER\TestADO\MyDB.mdb;Mode=ReadWrite;Persist Security Info=False';
    Better_ADO_DataSet := Thr_BADODataset.Create(false,handle,NIL,filename{PromptDataSource(1,'')},NIL,fwork);

    combobox1.Items.Add(IntToStr(Better_ADO_DataSet.ThreadID));
    ObjList.Add(Better_ADO_DataSet);
  end;
  label1.caption:='Startzeit: '+timetostr(NOW);
end;

//----------------------------------------------------------------------------//

procedure Te.FormDestroy(Sender: TObject);
var i:word;
begin
for i:=0 to objlist.Count-1 do
 begin
 if (ObjList.Items[i] is Thr_BADODataSet) then
  with (Objlist.Items[i] as Thr_BADODataSet) do
   begin
    try
     Terminate;
     Waitfor;
     if assigned(fwin) then
        fwin:=NIL;
    finally
     Free;
    end;
   end;
end;
 ObjList.Free;
 objlistDebugWin.Free;
end;

end.//--------------------------------FIN-------------------------------------//


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:
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:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
// Nun der Thread (Thr_BADODataset), der wichtigste Teil


unit thr_betteradodataset;

interface

uses
  Windows, SysUtils, Classes, ADODB, BetterADODataset, StdCtrls, TCIDebug_101, ComObj, DB, DBClient;

const
  RANDOMWERT = 10;

type
  TThisWork = (R,W,A,SQL,Nothing);
  ComboArray = array [0..3] of TThisWork;

type
  Thr_BADODataset = class(TThread)
  private
   query   : TADOQuery;
   DataSet : TBetterADODataSet;
   counter,maxcount : cardinal;
   checkbool : boolean;
   flist   : string;
   operation : ComboArray;
   howner:hwnd;
   procedure mySleep(NumberOfSeconds:LongWord);
   procedure Attach;
   procedure Read;
   procedure SQLRead;
   procedure Write;
   procedure DataSetStandardConfig;
   function  getPCName : ShortString;
  public
   fwin    : TDebugWin;
   Constructor Create(CreateSuspended: Boolean; Owner : hwnd; Conn : TADOConnection; Const TCI_CONNECTIONSTRING : string; myShow : TDebugWin; WorkType : ComboArray);
   Destructor Destroy; Override;
   property list : string read flist;
   property count : cardinal read counter;
   property max : cardinal read maxcount;
  protected
    procedure Execute; override;
  published

  end;

implementation

uses Unit1;

{ Thr_BetterADODataset }


//----------------------------------------------------------------------------//

procedure Thr_BADODataset.Execute;
var i:byte;
begin
  flist:='ThreadId '+inttostr(threadid)+'|';
  repeat
  mySleep(1000+(random(RANDOMWERT)+1));
  for i:=low(operation) to high(operation) do
   begin
   dataset.close;
    case operation[i] of
     R       : read;
     A       : Attach;
     W       : write;
     SQL     : SQLRead;
     Nothing : mysleep(100);
    end;
   mySleep(1000+(random(RANDOMWERT)+1));
   if checkbool then flist:=flist+'T'+inttostr(counter)+'|'
   else if not checkbool then flist:= flist+'F'+inttostr(counter)+'|';
  end;
  until terminated;

end;

//----------------------------------------------------------------------------//

procedure Thr_BADODataset.SQLRead;
 begin
 try
  dataset.Close;
  dataset.CommandType:=cmdtext;
  dataset.CommandText:='SELECT [Kunden-Nr] FROM Kunden';
  dataset.Open;
  try
   dataset.Requery;
   try
    if dataset.Recordset.RecordCount>0 then
     while not dataset.Eof do
      begin
      if not assigned(fwin) then break;
        fwin.Writeln([string(dataset.Recordset.Fields.Item[0].Value)]);
       if not dataset.FindNext then break;
     end;
   except
   end;
  finally
   DataSetStandardConfig;
  end;
 except
  beep;
 end;
end;

//----------------------------------------------------------------------------//

procedure Thr_BADODataset.Write;
var i,r:integer;
 begin
 try
  if dataset.recordcount<=0 then exit;
  inc(counter);
  r:=random(dataset.RecordCount-1);
  if counter > maxcount then maxcount:=counter;
  dataset.first;
  for i:=0 to r do dataset.FindNext;
  if (dataset.CanModify)AND(dataset.UpdateStatus<>usUnModified) then
   begin
    dataset.UpdateCursorPos;
    dataset.Recordset.Fields.Item[2].Value:='OVERRIDE '+getPCName+' '+inttoStr(counter);
    dataset.Recordset.Fields.Item[1].Value:='ID_'+inttostr(ThreadID);
  end;
  dataset.Last;
 except
  beep;
 end;
end;

//----------------------------------------------------------------------------//

procedure Thr_BADODataset.Attach;
var param1,param2:string;
 begin
  checkbool:=false;
  inc(counter);
  param1:=getPCName+' '+inttoStr(counter);
  param2:=inttostr(threadid);
  if counter > maxcount then maxcount:=counter;
 try
  query.Close;
  query.SQL.Clear;
  query.SQL.Add('INSERT INTO Kunden(KontaktNachname,KontaktVorname) VALUES ("'+param1+'","'+param2+'")');//'INSERT INTO Kunden (KontaktNachname,KontaktVorname) VALUES ("'+param1+'","'+param2+'")';
  query.ExecSQL;
 except
 end;
end;

{ //attach mit append
procedure Thr_BADODataset.Attach;
 begin
  checkbool:=false;
  inc(counter);
  if counter > maxcount then maxcount:=counter;
  if not dataset.Active then dataset.Open;
  if (dataset.CanModify)then
 try
    //dataset.FieldByName('Kunden-Nr').Required:= FALSE;
    dataset.Append;
    dataset.FieldValues['KontaktVorname']:=getPCName+' '+inttoStr(counter)+' | '+TimeToStr(Now);
    dataset.FieldValues['KontaktNachname']:='ID_'+inttostr(ThreadID);
    dataset.Post;
    checkbool:=true;
 except
 end;
end;
}

//----------------------------------------------------------------------------//

procedure Thr_BADODataset.Read;
var i,j : word;
    buf :string;
 begin
 try
   buf:='';
   if dataset.Recordset.RecordCount>0 then begin
   if not dataset.FindFirst then exit;
   for j:=0 to dataset.Recordset.RecordCount-1 do
    begin
       for i:=0 to dataset.Recordset.Fields.Count-1 do
            buf:=buf+' | '+string(DataSet.Recordset.Fields.Item[i].Value);
       if  buf<>'' then
        if not assigned(fwin) then break else fwin.Writeln([buf]);
       buf:='';
    if terminated then exit else dataset.FindNext;
   end;
  end;
 except
  beep;
 end;
end;

//----------------------------------------------------------------------------//

Constructor Thr_BADODataset.Create(CreateSuspended: Boolean; Owner : hwnd;  Conn : TADOConnection; Const TCI_CONNECTIONSTRING : string; myShow : TDebugWin; WorkType : ComboArray);
var buffer:string;
  Procedure ConnectionStringDiaglog;
   begin
    Dataset.ConnectionString := PromptDataSource(0,'');
  end;// function
 begin
  inherited Create(CreateSuspended);
   operation := Worktype;
   counter:=0;
   maxcount:=0;
   fwin:=myShow;
   howner := owner;

   DataSet:=TBetterAdoDataSet.Create(NIL);
   if Assigned(Conn) then
     DataSet.Connection:=Conn
    else
     begin
      if TCI_CONNECTIONSTRING<>'' then
       begin
        buffer:=pchar(@TCI_CONNECTIONSTRING[pos('Source=',TCI_CONNECTIONSTRING)+7]);
        buffer:=copy(buffer,1,pos(';',buffer)-1);
      end else buffer:='';
      if FileExists(buffer) then // if exists -> source
         dataset.ConnectionString:=TCI_CONNECTIONSTRING
       else
        begin
         ConnectionStringDiaglog;
        end;
    end;
    query := TADOQuery.Create(NIL);
     with query do
      begin
       ConnectionString:=dataset.ConnectionString;
       CursorLocation:=clUseServer;
       CursorType:=ctkeyset;
       LockType:=ltPessimistic;
     end;
    DataSetStandardConfig;
end;

//----------------------------------------------------------------------------//

procedure Thr_BADODataset.DataSetStandardConfig;
 begin
   if dataset.Active then dataset.close;
    with DataSet do
     begin
      CursorLocation:=clUseServer;
      CursorType:=ctkeyset;
      CommandType:=cmdTableDirect;
      LockType:=ltPessimistic;
      CommandText:='Addressen';
    end;{with}
   if not dataset.Active then dataset.Open;
end;

//----------------------------------------------------------------------------//

Destructor Thr_BADODataSet.Destroy;
 begin
  query.free;
  if dataset.Active then dataset.Close;
  DataSet.Free;
  inherited Destroy;
end;

//----------------------------------------------------------------------------//

procedure Thr_BADODataSet.mySleep(NumberOfSeconds:LongWord);
var i:word;
 begin
  for i:=0 to (NumberOfSeconds div 10) do if not Terminated then sleep(10) else break;
end;

//----------------------------------------------------------------------------//

function Thr_BADODataset.getPCName : String;
 var buffer : array [0..21] of AnsiChar;
     dw     : dword;
 begin
  dw:=high(buffer);
  GetComputerName(buffer,dw);
  result:=pchar(@buffer[0]);
end;

//----------------------------------------------------------------------------//

INITIALIZATION
randomize();

end.//--------------------------------FIN-------------------------------------//

_________________
mfg
Tana´Ri