2012-09-05 14 views
9

Tak więc po naruszeniu ograniczenia integralności za pomocą Doctrine2, EntityManager lubi zamknąć w sposób, który uniemożliwia dalsze korzystanie z tego EntityManager. Dominującą myślą wydaje się, że powinieneś stworzyć nowy EntityManager, a nie pozwolić sobie na uchwycenie tego prostego wyjątku i poradzić sobie z nim w zgrabny sposób (cudowny projekt tam faceci/sarkazm).Radzenie sobie z zamkniętym EntityManager z Bisna/Doctrine2

Jednak pojawia się problem podczas korzystania z biblioteki Bisna/ZF 1.12 z zamkniętym menedżerem encji. Biblioteka Bisna nie zapewnia publicznej metody tworzenia nowego EntityManager o tej samej nazwie (tj. "Default") po zamknięciu w klasie Container.

Moje pytanie brzmi, jak najlepiej radzić sobie z tym problemem. Po prostu musi być sposób na odzyskanie wdzięku po naruszeniu ograniczenia integralności.

+0

korzystania z rejestru doktryny mogłaby przywrócić zamkniętą kierownika podmiotu. – Florian

+0

zobacz https://github.com/symfony/symfony/issues/5339 – Florian

Odpowiedz

2

zamiast próbuje odzyskać z tych sytuacji, należy skupić się na zapobieganiuintegralności naruszenia ograniczeń:

  • Jeśli trafisz klucz obcy, nie jesteś wiążąc podmioty razem w prawo sposób.
  • Jeśli trafisz na unikalne ograniczenie, powinieneś sprawdzić bazę danych pod kątem możliwych duplikatów danych przed próbą ich utrwalenia.
  • Jeśli trafisz innego rodzaju ograniczeń i nie wiem jak temu zapobiec, należy zapytać :)

UPDATE:

Powodem Doctrine2 zamyka EntityManager jest, ponieważ w większości przypadków jest to nie jest już bezpieczny w użyciu. Jego UnitOfWork zawiera operacje, których nie można wykonać (stąd wyjątek, który został zgłoszony).

Masz rację, że biblioteka Bisna nie obsługuje tworzenia nowego EntityManager. Możesz go rozszerzyć, aby samemu wdrożyć taką funkcjonalność.

Innym rozwiązaniem byłoby handle transactions manually:

$em->getConnection()->beginTransaction(); // suspend auto-commit 
try { 
    // do some work 
    $user = new User; 
    $user->setName('George'); 
    $em->persist($user); 
    $em->flush(); 
    $em->getConnection()->commit(); 
} catch (Exception $e) { 
    $em->getConnection()->rollback(); 
    $em->clear(); // in stead of $em->close(); 
    throw $e; 
} 

Zastępując $em->close() z $em->clear() zachować EntityManager otwarte i czyste, aby ponownie użyć.

I bardzo zachęcamy albo blisko lub jasne EntityManager, a dane w nim jest (prawie zawsze) nie jest już do użytku.

+1

Istnieją scenariusze, kiedy po prostu nie wiesz wcześniej. Prostym przykładem jest wielu klientów połączonych z bazą danych, co jest oczywiście powszechne. Mogą wstawiać zduplikowane dane zaraz po sprawdzeniu, ale zanim klient zapisze dane. Po prostu nie można temu zapobiec, używając wyłącznie blokad baz danych o wyłącznym typie (a my naprawdę tego nie chcemy). Dlatego odzyskanie tego typu błędu jest raczej niezbędne. –

+0

Zgadzam się, że powinieneś odzyskać w tym konkretnym przypadku, ale najprawdopodobniej nie będziesz potrzebować nowego EntityManager w tym samym żądaniu (ponieważ użytkownik/klient musi dokonać ponownej oceny jego/jej/jej danych wejściowych). PS: Doctrine zapewnia blokowanie, zobacz http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/annotations-reference.html#version i http://docs.doctrine-project.org /en/2.0.x/reference/transactions-and-concurrency.html#locking-support –

0

Ręczne przeprowadzanie transakcji nie sprawiało mi żadnej różnicy. Doctrine nadal zamknął Entity Manager, nawet jeśli użyłem tylko metody clear. Rozwidlałem Bisnę i wprowadziłem pewne modyfikacje do klasy Container, dodając metodę "resetEntityManager", która wydaje się działać dobrze.

Więc teraz mój kod wygląda następująco:

try { 
    $user = new User; 
    $user->setName('George'); 
    $em->persist($user); 
    $em->flush(); 
} catch (Exception $e) { 
    $dc = \Zend_Registry::get('doctrine'); //returns Bisna\Doctrine\Container 
    $em = $dc->resetEntityManager(); //returns the new instance 
    throw $e; 
} 

Revised klasa Pojemnik jest tutaj:

https://github.com/ajlozier/zendframework1-doctrine2/blob/ea46703e909149cba43edca56c91d5de2ab7a7f9/library/Bisna/Doctrine/Container.php

Powiązane problemy