Ich habe eine Viele-zu-Viele-Beziehung zwischen Fotos und Tags: Ein Foto kann mehrere Tags haben und mehrere Fotos können dieselben Tags verwenden.Welcher Algorithmus für eine Viele-zu-Viele-Beziehung in NHibernate verwendet wird
Ich habe eine Schleife, die die Fotos in einem Verzeichnis scannt und dann NHibernate hinzufügt. Einige Tags werden zu den Fotos während dieses Prozesses hinzugefügt, z. Ein 2009-Tag, wenn das Foto im Jahr 2009 aufgenommen wurde.
Die Tag-Klasse implementiert Equals und GetHashCode und verwendet die Name-Eigenschaft als einzige Signatureigenschaft. Sowohl Photo als auch Tag haben Ersatzschlüssel und sind versioniert.
Ich habe einige Code ähnlich dem folgenden:
public void Import() {
...
foreach (var fileName in fileNames) {
var photo = new Photo { FileName = fileName };
AddDefaultTags(_session, photo, fileName);
_session.Save(photo);
}
...
}
private void AddDefaultTags(…) {
...
var tag =_session.CreateCriteria(typeof(Tag))
.Add(Restriction.Eq(“Name”, year.ToString()))
.UniqueResult<Tag>();
if (tag != null) {
photo.AddTag(tag);
} else {
var tag = new Tag { Name = year.ToString()) };
_session.Save(tag);
photo.AddTag(tag);
}
}
Mein Problem ist, wenn der Tag nicht existiert, zum Beispiel das erste Foto eines neuen Jahres. Die AddDefaultTags-Methode prüft, ob das Tag in der Datenbank vorhanden ist, erstellt es und fügt es NHibernate hinzu. Das funktioniert hervorragend, wenn Sie ein einzelnes Foto hinzufügen, aber beim Importieren mehrerer Fotos im neuen Jahr und innerhalb derselben Arbeitseinheit schlägt es fehl, da es in der Datenbank noch nicht vorhanden ist und erneut hinzugefügt wird. Beim Abschließen der Arbeitseinheit schlägt sie fehl, da versucht wird, zwei Einträge in der Tabelle Tags mit demselben Namen hinzuzufügen ...
Meine Frage ist, wie Sie sicherstellen, dass NHibernate nur versucht, ein einzelnes Tag in der Datenbank zu erstellen die obige Situation. Muss ich eine Liste neu hinzugefügter Tags selbst verwalten oder kann ich das Mapping so einrichten, dass es funktioniert?
Es tut mir leid, dass ich diesen Teil nicht gut erklärt habe. Mein FlushMode ist auf Nie eingestellt. Ich arbeite in einer Arbeitseinheit, in der ich nach Abschluss einen expliziten Flush mache. Oh, und auch innerhalb einer Transaktion. – HakonB
Oh. OK. Wenn Sie absolut gegen einen Aufruf der DB an der Stelle im Code sind, an der Sie ein neues Tag einfügen, glaube ich, dass es keine andere Möglichkeit gibt, als die Tags selbst zu verfolgen. Aber ich sehe nicht, warum Sie es nicht löschen würden, Sie können immer noch Ausnahmen in der Arbeitseinheit zurücksetzen. – asgerhallas
Werfen Sie einen Blick hier, für die Rollback-Güte und Vorbehalte: http://objectissues.blogspot.com/2004/12/understanding-hibernate-transaction.html – asgerhallas