[gelöst]SQL Server: Fehlermeldung "Ein anderer Anwender"

24. März 2009 09:23

Hallo,

habe ein seltsames Verhalten bei einem Report:

In meiner nativen Datenbank funktioniert der Report einwandfrei. Der Report soll mehrere Objekte in allen Mandanten
des Kunden abgleichen. Wobei jedoch immer nur ein Mandant nach dem anderen pro Lauf abgeglichen wird mit dem
Hauptmandant. Dabei läuft der Report im Hauptmandant ab.

Beim Kunden auf einem SQL-Server kommt nach
mehrmaligen erfolgreichen Durchläufen plötzlich die Fehlermeldung "Ein anderer Anwender hat den Datensatz .....geändert.
Bitte beginnen Sie die Aktivität neu"

Ich bin aber zu diesem Zeitpunkt als einziger auf der Datenbank.
Nach diesem Fehler bleibt der Report immer an der gleichen Stelle hängen. (Ein Datensatz.Modify;)
Nach einem auskommentieren dieses Befehls läuft der Report wieder ein paar mal.
Dann bleibt er aber bei einem anderen Objekt welches zu modifizieren ist hängen mit der gleichen Fehlermeldung.

Mich wundert das der Report einige Male erfolgreich gelaufen ist und dann plötzlich auf den Fehler läuft.

weiß jemand etwas über dieses Verhalten?
Zuletzt geändert von Pegasus am 1. April 2009 15:50, insgesamt 1-mal geändert.

Re: SQL Server: Fehlermeldung "Ein anderer Anwender hat.."

24. März 2009 16:02

Also zunächst einmal sollte man NIEMALS auf "native" für einen SQL Server entwickeln - das wird früher oder später IMMER zu Problemen führen!

Der Fehler den Du beschreibst wird entweder durch "RECOMPILE Hints" erzeugt, wenn die eingestzten NAV und SQL Versionen dazu noch nicht richtig in der Lage sind (Updates installieren), oder durch SQL untauglich Programmierung.

Ein klassisches Beispiel für eine solche Programmierung:

Code:
Record.SETCURRENTKEY(Field1);
Record.SETRANGE(Field1, Value1);
IF Record.FINDSET THEN
  REPEAT
    Record.Field1 := Value2;
    Record.MODIFY;
  UNTIL Record.NEXT = 0;


Hier wird ein SQL Cursor mit einer Menge von DS aufgebaut, bei dem "Field1" ein Definitionskriterium war ("= Value1"). Nun wird in der Schleife dieses Kriterium geändert ("= Value2"), damit wird der Cursor ungültig und muss neu aufgebaut werden. In diesem Extrem-Beispiel wird damit auch noch die Sortierung geändert, so dass es im hier schlimmsten Fall auch zu Endlos- oder Einmal-SChleifen kommen kann.
Man kann dieses Verhalten ein wenig beeinflussen indem man FINDSET(TRUE) oder FINDSET(TRUE, TRUE) verwendet, aber am sinnvollsten ist es, die Änderungen in einer zweiten Instanz des Records durchzuführen:
Code:
Record.SETCURRENTKEY(Field1);
Record.SETRANGE(Field1, Value1);
IF Record.FINDSET THEN
  REPEAT
    Record2.GET(Record1.Primary_Key);
    Record2.Field1 := Value2;
    Record2.MODIFY;
  UNTIL Record.NEXT = 0;


Habt ihr solche Algorithmen im Code?

Re: SQL Server: Fehlermeldung "Ein anderer Anwender hat.."

24. März 2009 20:04

Alternativ biete ich noch ein anderes Konstrukt an:

Code:
Record.SETCURRENTKEY(Field1);
Record.SETRANGE(Field1, Value1);
IF Record.FINDSET THEN
  REPEAT
    Record.Field2 := Value2;
    ChangeValueInSecondInstance(Record);
    Record.MODIFY;
  UNTIL Record.NEXT = 0;

EXIT;


FUNCTION ChangeValueInSecondInstance(Record)
  IF Record.Field1 = 1 THEN BEGIN
    Record2.GET(Record1.Key1);
    Record2.Field2 := 0;
    Record2.MODIFY;
  END;
END;


Oder auch das gleiche über globale Record-Variablen. Also die Änderung von Daten in einer zweiten Instanz inkl. MODIFY, nach Änderung von Feldwerten in Instanz 1 mit darauf folgendem MODIFY. Damit entspricht die Version der Instanz 1 im Speicher nicht mehr der tatsächlich in der Datenbank enthaltenen Version und es kommt zu obigem Fehler.

Habe heute nicht die Erklär-Bär Maske auf, aber ich hoffe mich verständlich genug auszudrücken :)

Re: SQL Server: Fehlermeldung "Ein anderer Anwender hat.."

25. März 2009 09:17

Vielleicht entspricht mein Code dem was ihr beide beschreibt, aber ich kann da nicht so den Finger drauf legen:

Code:
IF MandantRec.FIND('-') THEN
  REPEAT
    GlobalRec.CHANGECOMPANY(MandantRec.Name);
    IF GlobalRec.GET(Record.Code) THEN BEGIN
      IF (GlobalRec.Description <> Record.Description) THEN BEGIN
              GlobalRec := Record;
              GlobalRec.MODIFY;
      END;
  UNTIL MandantRec.NEXT = 0;


Wobei in dieser "Updateschleife" nur ein Mandant gefunden werden kann. er also einmal pro Tabelle dort reingeht.
Wie kann denn so ein Code "zig-mal" gut gehen, und dann plötzlich "klemmen".
Er soll ja den Datensatz in einem Mandanten mit dem in einem "Prüfmandanten" abgleichen.

Re: SQL Server: Fehlermeldung "Ein anderer Anwender hat.."

25. März 2009 10:30

die ursache könnte sein, dass du den Mandantenrec nicht filterst.
hier sollte meines erachtens noch stehen
Code:
mandantrec.setfilter(name,'<>%1',companyname);

sonst versuchst du den Datensatz der ja die Änderung hervorruft nochmal zu ändern. das würde die Fehlermeldubg erklären.

Re: SQL Server: Fehlermeldung "Ein anderer Anwender hat.."

25. März 2009 10:58

ne sorry...das passiert vorher auch schon.....mit genau dem code den du beschrieben hast.

ich bin auch mit dem debugger über den code gegangen. und dort hat er genau die richtigen daten
in den richtigen variablen.

er versucht nun tatsächlich in einem anderen mandanten die beschreibung eines datensatzes zu modifizieren mithilfe
des richtigen datensatzes aus dem "prüfmandanten"

Re: SQL Server: Fehlermeldung "Ein anderer Anwender hat.."

25. März 2009 11:42

mal nur geraten,
evtl verschluckt sich navision bei der zuweisung
Code:
globrec := record;

versuchs mal mit
transferfields

Re: SQL Server: Fehlermeldung "Ein anderer Anwender hat.."

26. März 2009 21:38

Ich hatte denselben Fall, die Lösung war tatsächlich TRANSFERFIELDS anstatt der Zuweisung Record1 := Record2
Es hat was wahrscheinlich mit dem Zeitstempel des records zu tun.

Re: SQL Server: Fehlermeldung "Ein anderer Anwender hat.."

27. März 2009 09:21

zeitstempel glaub ich nicht, ich vermute eher, dass über die Zuweisung auch die Company mit zugewiesen wird.

Re: SQL Server: Fehlermeldung "Ein anderer Anwender hat.."

1. April 2009 15:50

Also für mich war jetzt die Lösung ein Locktable für diese Tabelle.

Da mein Report eh nur laufen darf wenn keiner diese Tabellen benutzt.
Obwohl ich damit nicht ganz glücklich bin.
Werde beim nächsten mal an das Transferfields denken.

Trotzdem Danke für die Lösungsansätze