[Gelöst] [CC] Fehlermeldung: Keine Änderung vor Transaktion

13. Dezember 2018 10:06

Ich bekomme bei Navision 2009 im CC in einer Form die Fehlermeldung "Sie können keine Änderung an der Datenbank vornehmen, ehe eine Transaktion gestartet wurde." Soweit ich die Recherchen hier im Forum und auf Google richtig verstehe, hängt das damit zusammen, dass keine Transaktion durch den User angestoßen worden ist. Das ist aber - meiner Meinung nach - hier nicht der Fall: Der Fehler tritt auf, wenn der User in der Form ein Feld nach Änderung des Feldinhalts verlässt, wobei im "OnValidate"-Trigger weiterer Code aufgerufen wird: Über eine weitere Funktion in der Form eine Codeunit und darüber ein Validate eines Tabellenfelds. Darin steht das MODIFY einer weiteren (dritten!) Tabelle, die den Fehler laut Debugger auslöst.

Irgendwer eine Idee vielleicht? Zu Grunde liegt ja tatsächlich eine Usereingabe, von daher verstehe ich nicht ganz, wieso die Transaktionsbezogene Fehlermeldung an dieser Stelle kommt.
Zuletzt geändert von mideg am 14. Dezember 2018 16:48, insgesamt 2-mal geändert.

Re: [CC] Fehlermeldung: Keine Änderung vor Transaktion

13. Dezember 2018 10:21

wobei im "OnValidate"-Trigger weiterer Code aufgerufen wird

Ist es der OnValidate-Trigger der Form oder der Tabelle, der die Codeunit aufruft?

Versuch mal folgendes:
  • Den Code von Form nach Tabelle verschieben (falls möglich)
  • Vor Aufruf der Codeunit ein Rec.MODIFY absetzen.

Re: [CC] Fehlermeldung: Keine Änderung vor Transaktion

13. Dezember 2018 10:51

Vielen lieben Dank zuallererst!

Natalie hat geschrieben:
wobei im "OnValidate"-Trigger weiterer Code aufgerufen wird

Ist es der OnValidate-Trigger der Form oder der Tabelle, der die Codeunit aufruft?


An der Stelle ist es der OnValidate der Form.

Der Ablauf ist wie folgt:
  • Das Feld F in der Form A mit Sourcetable X wird vom User verändert.
  • OnValidate der Form A
  • Funktion der Form A
  • Funktion in Codeunit B
  • OnValidate eines Felds G aus Tabelle Y
  • Funktion in Tabelle Y
  • Beim Aufruf eines MODIFY(TRUE) von Tabelle Z wird der oben genannte Fehler geworfen.

Versuch mal folgendes:
  • Den Code von Form nach Tabelle verschieben (falls möglich)
  • Vor Aufruf der Codeunit ein Rec.MODIFY absetzen.


Der erste Vorschlag ist leider nicht leicht umzusetzen. Der zweite ist bereits so umgesetzt, d.h. vor dem Aufruf von Codeunit B ist bereits ein MODIFY.

Was mich auch wundert: Ein in meinen Augen vollständig analog aufgebautes anderes Feld mit demselben Ablauf im Code wirft den Fehler nicht.

Eidt: Fixed the list.

Re: [CC] Fehlermeldung: Keine Änderung vor Transaktion

13. Dezember 2018 11:24

mideg hat geschrieben:Der Ablauf ist wie folgt:
  • Das Feld F in der Form A mit Sourcetable X wird vom User verändert.
  • OnValidate der Form A
  • Funktion der Form A
  • Funktion in Codeunit B
  • OnValidate eines Felds G aus Tabelle Y
  • Funktion in Tabelle Y
  • Beim Aufruf eines MODIFY(TRUE) von Tabelle Z wird der oben genannte Fehler geworfen.


Dann Trick 17: Erstelle einen ProcessingOnly-Report, der die Codeunit-B-Funktion aufruft. Ruf in Form A diesen Report statt der Codeunit-Funktion auf.

Re: [CC] Fehlermeldung: Keine Änderung vor Transaktion

13. Dezember 2018 11:28

Das versuche ich. Ich versuche vorher noch, zu verstehen, warum das in einem Fall funktioniert (und wohl vorher auch schon funktioniert hat) und im anderen Fall bzw. jetzt nicht.

Besten Dank für Deine Hilfe. Das Forum hier könnte echt Eintritt nehmen. :-)

Re: [CC] Fehlermeldung: Keine Änderung vor Transaktion

13. Dezember 2018 11:30

mideg hat geschrieben:Das Forum hier könnte echt Eintritt nehmen. :-)
Meine Kontonummer ist …. :mrgreen: :mrgreen: (kleiner Scherz)

Re: [CC] Fehlermeldung: Keine Änderung vor Transaktion

13. Dezember 2018 12:54

Ich markiere den Beitrag später noch als [GELÖST].

Ich bin mir noch nicht ganz sicher, ob das schon gelöst ist. :-?

In der Codeunit wird zuallererst SELECTLATESTVERSION aufgerufen. Kann das das fehlerhafte Verhalten beeinflussen?

Wie gesagt, was mich stutzig macht, ist, dass es bei einem synchron ablaufenden Feld funktioniert. Ich finde den Unterschied nicht. Da bin ich gerade dran, zu verstehen, wo die Programmabläufe bei den beiden Felder unterschiedlich laufen.

Re: [CC] Fehlermeldung: Keine Änderung vor Transaktion

13. Dezember 2018 12:58

Hallo,

ich hatte dieses Problem in 2009 auch schon mal. Es war aber - glaube ich - in einem späteren technischen Build gelöst.

Gruß Fiddi

Re: [CC] Fehlermeldung: Keine Änderung vor Transaktion

13. Dezember 2018 15:52

Nachträglich geschriebener Disclaimer: Ich poste hier jetzt nen ziemlichen Wall of Code. Ich hoffe, das ist ok. Das so zu verschriftlichen hilft vor allem mir, durch Erklären der Vorgänge zu verstehen, wo der Fehler liegen könnte. Wenn einer von Euch sich das auch anschaut, finde ich das prima und bin sehr dankbar, aber fühlt Euch bitte nicht verpflichtet. :-)
Natalie hat geschrieben:Dann Trick 17: Erstelle einen ProcessingOnly-Report, der die Codeunit-B-Funktion aufruft. Ruf in Form A diesen Report statt der Codeunit-Funktion auf.

Hm - ich bekomme den Fehler leider immer noch, auch mit dazwischengeschaltetem Report. :-/ Bei den Feldern, bei denen es auch bisher funktioniert, funktioniert es auch mit dazwischengeschaltetem Report.

Jetzt habe ich auch gesehen, dass da einiges mit Temporary-Records und RecRefs bzw. FieldRefs gearbeitet wird. Bin erst seit anderthalb Monaten hier, kenne die technischen Strukturen noch nicht so gut. Refs sind kein Bereich, in dem ich viel Erfahrung habe. Ich versuche mal, mehr für mich als für Euch nette Helfer, das nochmal zu verschriftlichen. Damit ich nicht noch mehr durcheinander komme, verwende ich die Original IDs - das sollte nicht zuviel verraten. ;-)

Der ganze Aufruf beginnt in Form 50274. Die Form bezieht sich auf Table 27, beinhaltet aber die globale temporäre Variable TempItemSub vom Table 50273. Die beiden Felder in Frage sind "Gruppierungsebene 1" vom Typ Text und das Feld "Warnhinweis" vom Typ Option, beide aus der Table 50273. (Das sind zwei beispielhaft ausgewählte Felder, eines, das funktioniert, eines, das nicht.) In beiden On-Validate-Triggern dieser Felder auf der Form steht im Prinzip derselbe Code (statt "Warnhinweis" halt der entsprechende Feldname beim anderen):
Code:
ChangeItemSub(TempItemSub.FIELDNO(Warnhinweis));

Es wird also die Feldnummer des Felds an die lokale Funktion ChangeItemSub übergeben.

Diese sieht ungefähr so aus (p_FieldNo ist dabei der Parameter):
Code:
CurrForm.SAVERECORD;
MODIFY;
CUFunctions.ChangeItemSub(TempItemSub,"No.",p_FieldNo);
MultiEditItemSub(p_FieldNo);


CUFunctions verweist auf Codeunit 50271. Es wird also die temporäre ItemSub, die "No." aus Item und die zuvor ermittelte Feldnummer übergeben. Hier wird's etwas komplizierter. Ich habe unwichtigen Code mal rausgekürzt und dafür im Code kommentiert:

Code:
ChangeItemSub(VAR p_TempItemSub : TEMPORARY Record "ERVIN Item Sub";p_ItemNo : Code[20];p_FieldNo : Integer)

SELECTLATESTVERSION;
[..]
IF NOT l_ItemSub.GET(p_ItemNo) THEN BEGIN            // Das ist im Prinzip derselbe Link, mit dem in der Form oben TempItemSub zu Item in Bezug steht, d.h. hier wird Tabelle 20273 nochmal als "normaler" Record geladen.
  l_ItemSub.INIT;
  l_ItemSub."Item No." := p_ItemNo;
  l_ItemSub.INSERT(TRUE);

  l_Item.GET(p_ItemNo);                                            // Hier wird Item nochmal geladen.
[..]
END;

l_xRecItemSub := l_ItemSub;                                     // Und noch eine ItemSub
l_xRecRef.GETTABLE(l_xRecItemSub);                        // Und eine Referenz auf die ItemSub

IF p_FieldNo <> 0 THEN BEGIN                                   // p_FieldNo ist ja die Feldnummer, die oben übergeben worden ist, sollte also ungleich 0 sein
  l_TempRecRef.GETTABLE(p_TempItemSub);             // lokale, temporäre RecRef
  l_TempFieldRef := l_TempRecRef.FIELD(p_FieldNo); // lokale, temporäre FieldRef

  l_ValiRecRef.GETTABLE(l_ItemSub);                         // lokale, nicht-temporäre RecRef
  l_ValiFieldRef := l_ValiRecRef.FIELD(p_FieldNo);       // lokale, nicht-temporäre FieldRef
  l_ValiFieldRef.VALIDATE(l_TempFieldRef.VALUE);      // <-- Hier wird der Fehler geworfen (***)
  l_ValiRecRef.SETTABLE(l_ItemSub);                          // Ich verstehe ehrlich gesagt nicht, warum hier überhaupt mit Recrefs gearbeitet wird. Hier wird l_ItemSub ja quasi wieder beschrieben. Der Typ von l_ItemSub steht aber doch die ganze Zeit fest?!?
END ELSE
  l_ItemSub.TRANSFERFIELDS(p_TempItemSub,FALSE);

[..]
l_ItemSub.MODIFY(TRUE);
[..]

An der (***)-Stelle springt er in die Table 50273. Hier die entsprechenden OnValidates. UpdateFkt ist in der Tabelle eine lokale Funktion. QSCheck auch, die aber nur Zugriffsrechte prüft und hier keine Rolle spielen sollte. (Auch ein Auskommentieren von QSCheck hat nicht geholfen.)
Code:
Group Text 1 - OnValidate()
UpdateFkt(FIELDNO("Group Text 1"));

Warnhinweis - OnValidate()
QSCheck(FIELDCAPTION(Warnhinweis));
UpdateFkt(FIELDNO(Warnhinweis));

Hier die UpdateFkt.
Code:
UpdateFkt(p_FieldNo : Integer)
OtherItem.RESET;
OtherItem.SETRANGE("No.","Item No.");
FieldChanged := FALSE;
txtWarnhinweis := '';
CE_Zeichen := FALSE;

IF OtherItem.FINDLAST THEN BEGIN
  CASE p_FieldNo OF
    15:                                                                                                                       // Feldnummer des Felds Warnhinweis
      BEGIN
        CASE Warnhinweis OF
          Warnhinweis::ohne : txtWarnhinweis := 'ohne';
          Warnhinweis::"<3 Jahre" : txtWarnhinweis := '< 3 Jahre';
          Warnhinweis::"<3 Jahre + Batterie" : txtWarnhinweis := '< 3 Jahre + Batterie';
          Warnhinweis::Batterie : txtWarnhinweis := 'Batterie';
        END;
        IF  OtherItem."Warning Text" <> txtWarnhinweis THEN
          BEGIN
            OtherItem."Warning Text" := txtWarnhinweis;
            FieldChanged := TRUE;
          END;
      END;
[..]
    26:                                                                                                                       // Feldnummer des Felds "Gruppierungsebene 1"
        IF OtherItem."Group Text 1" <> "Group Text 1" THEN
          BEGIN
            OtherItem."Group Text 1" := "Group Text 1";
            FieldChanged := TRUE;
          END;
[..]
  END;

  IF FieldChanged THEN
    BEGIN
      OtherItem."Modified from" := USERID;
      OtherItem."Modified on"  := TODAY;
      OtherItem."Item No." := ShowItemNo;
      OtherItem.MODIFY(TRUE);                                  // Hier wird der Fehler geworfen - aber nur bei Änderungen am Feld "Warnhinweis", nicht am Feld "Gruppierungsebene 1", obwohl der vorherige Codeverlauf in allen für mich relevant erscheinenden Fragen identisch ist.
  END;
END;


fiddi hat geschrieben:ich hatte dieses Problem in 2009 auch schon mal. Es war aber - glaube ich - in einem späteren technischen Build gelöst.

Ich bin überfragt und habe auch noch keinen Workaround. Technisch sind wir auf Version 6.00.35920. Ich habe ja den Verdacht, dass die Funktion noch nie funktioniert hat und das nur nicht aufgefallen ist, weil das "OtherItem" idR nicht vorhanden ist, wenn die Felder wie "Warnhinweis"gefüllt werden. Aber selbst, wenn das der Fall sein sollte, erklärt und löst das den Fehler ja nicht auf.

Was mir noch aufgefallen ist: Die beiden Felder, die den Fehler werfen, sind vom Typ Option. Alle anderen Felder sind vom Typ Text und funktionieren.

Re: [CC] Fehlermeldung: Keine Änderung vor Transaktion

13. Dezember 2018 16:03

Hallo,

besorge dir doch für deinen Testdatenbank mal einen neueren Build (ich habe 6.0.39038.0 als letzen Build)

Gruß Fiddi

Re: [CC] Fehlermeldung: Keine Änderung vor Transaktion

13. Dezember 2018 17:20

Ich werd' mal unseren Partner mit hinzuziehen und den auch nach einem aktuelleren Build fragen. Danke Euch.

(Das "gelöst" lass ich noch, ich sehe das hier noch nicht als gelöst an, wenn's Recht ist. Ich markiere es aber, wenn ich eine Lösung habe. :-) )

Re: [CC] Fehlermeldung: Keine Änderung vor Transaktion

14. Dezember 2018 10:47

Während ich auf unseren Partner warte, habe ich mal weiter experimentiert.

Auch eine Änderung direkt in der Tabelle (per RUN) löst den Fehler aus. Daraufhin habe ich die Funktion der Tabelle in einen Report ausgelagert, was auch nicht hilft. Jetzt werde ich mal im OnValidate der Tabelle die Updatefunktionen direkt ausführen. Vielleicht bringt das ja was. Ich berichte weiter. :-)

Update: Auch dabei wirft er den Fehler. Mal schauen, ob der Partner ein Buildupdate für machbar hält, dann bleibt uns das noch.

Re: [CC] Fehlermeldung: Keine Änderung vor Transaktion

14. Dezember 2018 16:48

Unser Partner konnte noch etwas herausfinden. Hätte ich vermutlich nie ausprobiert: Eine Eingabe/Änderung der Optionen per Tastatur, direkt in das Feld tippend, funktioniert. Eine Eingabe, die den Lookup mit der Maus oder F6 nutzt, führt zu dem Fehler. Vermutlich/vielleicht würde ein technisches Update daran etwas ändern, aber wir scheuen den Aufwand, zumal wir durch diese Erkenntnis nun endlich einen funktionierenden Workaround haben und dieser Fehler bei uns auch das erste Mal aufgetaucht ist und vermutlich auch in Zukunft nicht häufig auftreten wird.

Vielen Dank an die Hilfe hier im Forum, mal wieder, ihr seid alle toll!