2012-11-18 6 views
13

La domanda riguarda Doctirne, ma penso che possa essere estesa a molti ORM.Perché è necessario separare e unire le entità in un ORM?

Detach:

Un'entità si stacca da un EntityManager e quindi non più gestiti richiamando il metodo EntityManager#detach($entity) su di esso o cascata l'operazione di scollegamento ad esso. Le modifiche apportate all'entità distaccata , se presente (inclusa la rimozione dell'entità), non saranno sincronizzate nel database dopo che l'entità è stata scollegata.

unione:

entità Fondere riferisce alla fusione di (solitamente monofamiliare) entità nel contesto di un dell'EntityManager modo che diventino riusciti nuovamente. Per unire lo stato di un'entità in un EntityManager, utilizzare il metodo EntityManager#merge($entity). Lo stato dell'entità passata verrà unito a una copia gestita di questa entità e questa copia sarà restituita successivamente.

Capisco (quasi) come funziona, ma la domanda è: perché è necessario separare/fondere le entitaie? Puoi darmi un esempio/scenario quando queste due operazioni possono essere utilizzate/necessarie?

risposta

14

Quando devo staccare un'entità?
Staccare un'entità dal un EM (EntityManager) è ampiamente usato quando avete a che fare con più di una EM ed evitare conflitti di concorrenza, ad esempio:

$user= $em->find('models\User', 1); 
$user->setName('Foo'); 

// You can not remove this user, 
// because it still attached to the first Entity Manager 
$em2->remove($user); 
$em2->flush(); 

Non si può prendere il controllo di $user oggetto $em2 perché la sua sessione appartiene a $em che inizialmente carica il database $user. Come risolvere il problema sopra? È necessario staccare l'oggetto:

$user= $em->find('models\User', 1); 
$user->setName('Foo'); 

$em2->detach($user); 
$em2->remove($user); 
$em2->flush(); 

funzione Quando dovrei usare la fusione?
Fondamentalmente, quando si desidera aggiornare un'entità:

$user= $em->find('models\User', 1); 
$user->setName('Foo'); 

$em->merge($user); 
$em->flush(); 

La EM farà un confronto tra l'utente $ nella banca dati contro l'utente $ in memoria. Una volta che l'EM riconosce i campi modificati, li aggiorna solo e mantiene quelli vecchi.

Il metodo flush innesca un commit e il nome utente verrà aggiornato nel database

+0

Sono d'accordo con tutti detto tranne con quello che viene detto a livello. Il metodo flush sincronizza le entità con il database ma all'interno dei limiti della transazione. Questo viene a giocare su invocando una query all'interno della stessa transazione. In tal modo si garantisce che l'elaborazione della query tiene conto di questi stessi aggiornamenti delle transazioni. – Sam

+0

Sei corretto @Sam, ho sbagliato con il metodo flush. – manix

+1

Questa è una buona spiegazione (+1), ma perché si dovrebbe usare più di un gestore di entità in primo luogo? Non riesco a capirlo, mi dispiace, usando Doctrine sempre con un gestore di entità ... – gremo

1

Si avrebbe bisogno di staccare un soggetto quando si tratta di questioni di concorrenza.

Si supponga di utilizzare un'API asincrona che consente di richiamare il progetto. Quando si invia la chiamata all'API insieme all'istruzione di callback, è possibile che si stia ancora gestendo l'entità interessata dal callback e quindi si sovrascrivano le modifiche apportate dal callback.

-1

È inoltre possibile scollegare l'entità quando si dispone di dati pernamentari nel database, ma nel codice si modificano le entità in base all'account utente.

Ad esempio browser game che ha alcuni personaggi e alcuni attacchi da combattere. AttackOne usato da "UserFoo" (lvl 90) verrà modificato dal bonus meglio di usato da "UserBarr" (lvl 20), ma nel nostro database AttackOne tutto il tempo è lo stesso attacco