Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Klasy modelu a transakcje
Forum PHP.pl > Forum > PHP > Object-oriented programming
marcini82
Witam!

W aplikacji o strukturze wzorowanej na MVC mamy 2 klasy modelu A i B:
1. klasa A posiada metode wykonujaca skomplikowana operacje na bazie danych, skladajaca sie z wielu zapytan, ktore musza byc objete transakcja.
2. metoda klasy B wykonuje cos tam innego w bazie danych
Klasy kontrolerow akcji korzystaja z klas A i B.

Obie klasy i ich metody dotycza niezaleznych elementow serwisu i moga byc wywolywane oddzielnie.
Ale nagle okazuje sie, ze w pewnych przypadkach wykonanie obu operacji jedna po drugiej stanowi logiczna calosc: wykonywana akcja wymaga, aby wywolac metode klasy A, a nastepnie metode klasy B. Pytanie: jak objac pojedyncza transakcja obydwie operacje?

I teraz mamy rozne rozwiazania:
1. Klasa kontrolera akcji wywoluje najpierw metode klasy A a potem klasy B. W tym przypadku transakcja jest objeta tylko pierwsza operacja. Jesli klasa B nie bedzie w stanie wykonac operacji, to stan bazy bedzie nieprawidlowy, bo zmany spowodowane przez klase A nie beda uwzglednione w obszarze kontrolowanym przez klase B. Niefajnie.
2. Klasa kontrolera akcji wywoluje metode klasy A, a ta z kolei korzysta z klasy B. Ale teraz klasa A zaczyna byc zbytnio zalezna od klasy B. A co sie stanie, jesli operacje wewnatrz B rowniez beda objete transakcja? Tez niefajnie...

Macie inne pomysly? Jak zarzadzac transakcjami rozciagnietymi na rozne klasy, z ktorych kazda rowniez moze wymagac zdefiniowania transakcji w swoim wnetrzu?
DeyV
hmm. Chyba zrobiłbym to w ten sposób.

Kontroler
--
  1. <?php
  2. $ModelA; $ModelB;
  3.  
  4.  
  5. $ModelA->StartTr();
  6. $ModelB->StartTr(); // transakcja może być wystartowana wielokrotnie
  7.  
  8. try{
  9.  
  10.  $ModelA->run();
  11.  $ModelB->run(); // jeśli w A zostanie wywalony wyjątek - B się nawet nie zacznie wykonywać.
  12.  
  13.  
  14.  $ModelA->commit();
  15.  $ModelB->commit(); // w zależności od potrzeb - możemy zamknąć transakcje raz lub dla każdego przypadku osobno (chyba - podobnie jak niżej) 
  16.  
  17. }
  18. catch( Exception $e ){
  19.  $ModelA->RolbackTr();
  20.  $ModelB->RolbackTr(); // rollback może robić coś więcej, niż tylko wycofanie transakcji bazy danych 
  21.  // a zresztą - nawet gdyby robił tylko to, to i tak baza nie powinna (chyba) wyświetlić komunikatu błędu.
  22. }
  23. ?>


W ten sposób przenosimy nieco więcej pracy na kontroler, który musi pamiętać o każdorazowym uruchomieniu obsługi transakcji, ale to nie powinno stanowić problemu.
dr_bonzo
Z tym ze powinienes najpierw zcommitowac wewnetrzna tranzakcje, nie?
DeyV
a dlaczego?

Co to znaczy "wewnętrzna transakcja" ? Większość baz danych pozwala tylko na 1 poziom transakcji, który w całości jest akceptowany / wycofywany.

Więc w takim przypadku commit, gdzie by się nie pojawił, i tak zamknie nam wszystko.

Wywołanie 2 "pseudo commita" dałem tylko po to, by można w nim było zrobić jakieś rzeczy dodatkowe, ewentualnie po to, by zachować porządek w kodzie. (cały mechanizm może przecież być obsługiwany przez autmoat. )
dr_bonzo
Teraz juz rozumiem
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.