Gibt es beim Einfügen einer Entität mit Assoziationen eine Möglichkeit, einfach den FK zu verwenden, anstatt die Entität abzurufen?

Lesezeit: 4 Minuten

Benutzer-Avatar
blacktie24

Ich muss eine Entität einfügen, die Assoziationen hat.

Wenn ich bereits die FKs der zugehörigen Entitäten habe, gibt es eine Möglichkeit, die primäre Entität in die Datenbank einzufügen, wobei nur die FKs ausgefüllt sind?

Oder muss ich das immer

  • Abrufen der zugehörigen Entitäten über die FK’s,
  • Füllen Sie die Eigenschaften der primären Entität, die sich auf die Assoziationen beziehen,
  • und rufen Sie dann die persist-Methode auf.

  • Sie möchten also manuell eine Beziehung erstellen, indem Sie die ID einer vorhandenen Entität angeben, die verknüpft werden soll? Könnten Sie bitte einen Beispielcode für das hinzufügen, was Sie erreichen möchten?

    – Cobby

    22. März 2011 um 1:03 Uhr

  • Hey Cobby, danke für die Antwort. Ich habe ein Formular zum Erstellen von Benutzern, in dem Sie aus einer Auswahloptionsliste auswählen können, welche Rolle einem Benutzer zugewiesen werden soll (in diesem Fall kann der Benutzer nur eine Rolle haben). Wenn ich also die Formularübermittlung verarbeite, sollte ich einen Benutzernamen und eine Rollen-ID haben. Wenn ich den Benutzer speichern möchte, muss ich die zugehörige Rollenentität abrufen und in meinem Benutzerobjekt festlegen, um das Benutzerobjekt zu speichern? Oder kann ich einfach die roleId innerhalb des Benutzerobjekts festlegen und speichern?

    – blacktie24

    22. März 2011 um 1:16 Uhr

Benutzer-Avatar
timdev

Du willst ein Referenz-Proxy

Nehmen wir an, ich habe Posts und Tags. Ein Post hat viele Tags. Ich bekomme eine Reihe von Tags von dem Benutzer, der eine Reihe von Kontrollkästchen aktiviert hat.

Im Folgenden würden Tags zu einem vorhandenen Beitrag hinzugefügt, ohne zuerst jede Tag-Entität abzurufen. Dies geschieht durch die Verwendung von Referenz-Proxys, die von generiert werden EntityManager::getReference():

$tag_ids = $_POST['tag_id']; // an array of integers representing tag IDs.
$post = $em->getRepository('Post')->find($post_id); // returns a Post entity.

foreach($tags_ids as $tid){
   $post->addTag($em->getReference('Tag',$tid));
}
$em->persist($post);
$em->flush();

  • ahhh verstanden, das macht sehr viel Sinn, aber was passiert eigentlich im Backend? Wenn die Doktrin den Beitrag mit seinen neu hinzugefügten Tags beibehält, ersetzt sie dann am Ende die Proxys durch die tatsächlichen Entitäten und fügt diese Zuordnungen dann der Join-Tabelle hinzu?

    – blacktie24

    24. März 2011 um 0:19 Uhr

  • Ich bin mir nicht sicher, was Doctrine intern tut, aber ich gehe davon aus, dass es effizient ist – es fügt einfach ein und/oder aktualisiert es nach Bedarf. Wenn Sie einen Referenz-Proxy mit einer nicht vorhandenen ID erstellen, erhalten Sie wahrscheinlich eine Ausnahme, wenn Sie versuchen, flush() auszuführen, und die Transaktion wird zurückgesetzt. Aber verlassen Sie sich nicht auf mein Wort, testen Sie es selbst.

    – timdev

    24. März 2011 um 2:37 Uhr

  • ja ich werde es ausprobieren. Nochmals danke für deine Zeit, timdev, ich weiß das wirklich zu schätzen. Prost.

    – blacktie24

    24. März 2011 um 3:03 Uhr

  • Ich wusste überhaupt nichts über die Funktion EntityManager::getReference(), Mega-Fail. Sollte wahrscheinlich die API-Dokumentation noch einmal genauer lesen: P

    – Cobby

    11. Mai 2011 um 11:37 Uhr

  • +1 tolle Antwort @timdev. Wenn die ID nicht existiert, wird immer noch ein Referenz-Proxy generiert. Ich habe diese Frage hier gepostet. Ich verstehe immer noch nicht, warum die Doktrin einen Proxy für eine Entität generiert, die nicht existiert …

    – Mick

    9. Mai 2013 um 7:19 Uhr


In Bezug auf die Verwendung von a Referenz-Proxy

In meinen Untersuchungen ist dies nur teilweise eine Lösung, wie folgt:

Ja, Sie müssen den zugehörigen Datensatz nicht proaktiv abrufen (da Sie einen Proxy-Datensatz erstellen), aber wenn Sie die Aktualisierungstransaktion leeren (commitieren), führt sie immer noch zuerst eine Select-Anweisung aus, um den zugehörigen Datensatz abzurufen, und führt dies erst dann aus das update (alles in einem schlag auf die db).
Dies ist ineffizient und sollte nicht notwendig sein (wir haben die Fremdschlüssel-ID, warum den Datensatz abrufen …?)

Obwohl es sich nicht um eine vollständige Lösung handelt, erhalten Sie nur eine einzige Verbindung zur Datenbank (was gut ist) und einen leicht vereinfachten Code.

Ich bin mir nicht sicher, ob es dafür im Moment eine Lösung gibt …??
Hoffentlich werden die Lehrkörper in Zukunft aktualisiert und wenn wir die Proxy-Logik verwenden, sollten wir eine automatische Leistungsverbesserung erhalten …

Benutzer-Avatar
Cobby

Sie sollten die zu verknüpfende Entität abrufen und die Beziehung herstellen.

Ich vermute Sie könnte Geben Sie die Beziehung manuell an, indem Sie direkt über die DBAL-Schicht auf die Datenbank zugreifen, aber ich würde dies nicht empfehlen und habe es auch nicht versucht.

  • Cobby, ja, das hatte ich erwartet, aber warum genau sollte das nicht empfohlen werden, da es technisch gesehen eine zusätzliche Abfrage ersparen würde? Nochmals vielen Dank, dass Sie sich die Zeit genommen haben, meiner Frage nachzugehen, ich weiß das wirklich zu schätzen.

    – blacktie24

    22. März 2011 um 4:59 Uhr

  • Nach Ihrem Beispiel sollten Sie Ihre Rollen bereits zwischengespeichert haben (stellen Sie dies in der vorherigen Anfrage sicher, wenn sie für die Dropdown-Liste geladen werden). Es ist also nicht wirklich eine zusätzliche Abfrage. Auf diese Weise erhalten Sie eine sauberere Domänenschicht auf Kosten einer extrem geringen Leistungseinbuße.

    – Cobby

    22. März 2011 um 5:35 Uhr

Sie können dies mithilfe von entityManager::merge tun

$post = new Post();
$post->setPostCategory(['id' => 1]);
$em->persist($em->merge($post));
$em->flush();

1246590cookie-checkGibt es beim Einfügen einer Entität mit Assoziationen eine Möglichkeit, einfach den FK zu verwenden, anstatt die Entität abzurufen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy