Ich schreibe eine Blog-Engine als Lernübung. Ich weiß, es gibt viele Blog-Engines da draußen, aber ertragen Sie mit mir ...Wie zu vermeiden NHibernate.NonUniqueObjectException
Ich habe eine BlogPost-Entität, die eine Eigenschaft Tags hat, die eine IList der Tags zugeordnet ist. Die Methode BlogPost.SetTags (string) teilt die Zeichenfolge auf, erstellt neue Tag-Objekte mit dem angegebenen Tag-Namen und fügt sie der Liste hinzu. Gleiches für BlogPost.AddTag (string tagName). Wenn ich BlogPost.AddTag ("foo") anrufe, wo eine Tag-Entität mit dem Namen "foo" bereits existiert und in der Datenbank persistiert ist, realisiert nHibernate das und leitet den Post weiter.
Was würde ich gerne geschehen? mit dem vorhandenen Tag.
In der BlogRepository.Save() -Methode überprüfe ich, ob jedes Tag in der Liste Tags bereits existiert. Wenn nicht, speichere ich es mit einem Aufruf von TagRepository.Save (tag);
Das Problem ist, in dem folgenden Beispielcode erhalte ich einen Fehler "NHibernate.NonUniqueObjectException: ein anderes Objekt mit dem gleichen Bezeichner Wert wurde bereits mit der Sitzung verknüpft: Tag 1, der Einheit: CMS.Core. Model.Tag ", wenn ich versuche, ein BlogPost-Objekt mit einem vorhandenen Tag zu speichern. Wenn ich ein BlogPost-Objekt behalte, das nur neue Tags verwendet, werden diese erstellt, und alles ist in Ordnung.
Hinweis: Ich verwende auch den TagName als Primärschlüssel in der Datenbank für die Tabelle bp_Tags. Es erschien überflüssig, eine Ganzzahl oder eine GUID-PK zu verwenden, wenn die Tabelle nur eindeutige Tag-Namen speichert.
Mein nHibernate Konfiguration wie folgt aussieht:
<class name="CMS.Core.Model.Tag,CMS.Core" table="bp_Tags">
<id column="TagName" name="TagName" type="String" unsaved-value="">
<generator class="assigned" />
</id>
</class>
<class name="CMS.Core.Model.BlogPost,CMS.Core" table="bp_Content">
<id name="Id" column="Id" type="Int32" unsaved-value="0">
<generator class="native"></generator>
</id>
<property name="SubmittedBy" column="SubmittedBy" type="string" length="256" not-null="true" />
<property name="SubmittedDate" column="SubmittedDate" type="datetime" not-null="true" />
<property name="PublishDate" column="PublishDate" type="datetime" not-null="true" />
...
<bag name="_tagsList" table="bp_Tags_Mappings" lazy="false" cascade="all">
<key column="Target_Id" />
<many-to-many class="CMS.Core.Model.Tag,CMS.Core" column="TagName" lazy="false" />
</bag>
NHibernate.NonUniqueObjectException: ein anderes Objekt mit dem gleichen Kennungswert wurde bereits mit der Sitzung verknüpft ist: Tag 1 der Einheit: Bariliant.CMS.Core.Model. Tag
BlogPost post, post2;
using (UnitOfWork.Start())
{
post = BlogPostFactory.CreateBlogPost("test post", "test body");
post.Publish();
BlogRepository.Save(post);
UnitOfWork.Current.Flush();
post.SetTags("tag 1, tag 2");
BlogRepository.Save(post);
UnitOfWork.Current.Flush();
}
using (UnitOfWork.Start())
{
post2 = BlogPostFactory.CreateBlogPost("test post2", "test body");
post2.Publish();
BlogRepository.Save(post2);
UnitOfWork.Current.Flush();
post2.AddTag("tag 1");
BlogRepository.Save(post2); // throws
...
Irgendwelche Gedanken auf, was ich falsch mache und wie man es beheben?
Ich glaube, das Problem intern ist und kommt von der Art und Weise Sie die Liste der vorhandenen Tags erhalten zu Vergleichen Sie den neuen mit und wie Sie dem neuen BlogPost-Objekt einen vorhandenen zuweisen. Es wäre eine gute Idee, den Code des BlogRepository.Save(); Methode, bei der all dies geschieht, damit wir das Problem erkennen können. – tolism7