Piszę silnik bloga jako ćwiczenie uczenia się. Wiem, że istnieje wiele silników blogów, ale proszę o mnie ...Jak uniknąć NHibernate.NonUniqueObjectException
Mam podmiot BlogPost, który ma właściwość Znaczniki, które są ilistą tagów z nim związanych. Metoda BlogPost.SetTags (ciąg) dzieli ciąg znaków, tworzy nowe obiekty znaczników o określonej nazwie znacznika i dodaje je do listy. To samo dotyczy BlogPost.AddTag (string tagName).
To, co chciałbym mieć, to to, że kiedy zadzwonię do BlogPost.AddTag ("foo"), gdzie jednostka tagu o nazwie "foo" już istnieje i jest przechowywana w bazie danych, nHibernate właśnie to rozumie i drąży wpis z istniejącym tagiem.
W metodzie BlogRepository.Save() sprawdzam, czy każdy znacznik na liście znaczników już istnieje. Jeśli nie, zapisz go, wywołując TagRepository.Save (tag);
Problem polega na tym, że w poniższym przykładowym kodzie otrzymuję komunikat o błędzie "NHibernate.NonUniqueObjectException: inny obiekt o tej samej wartości identyfikatora był już powiązany z sesją: tag 1, entity: CMS.Core. Model.Tag ", gdy próbuję utrzymać obiekt BlogPost przy użyciu istniejącego tagu. Kiedy utrzymuję obiekt BlogPost, który używa tylko nowych tagów, są one tworzone i wszystko jest w porządku.
Uwaga Używam również nazwy znacznika jako klucza podstawowego w bazie danych dla tabeli bp_Tags. Wydawało się zbędne używanie liczby całkowitej lub GUID PK, gdy tabela przechowuje tylko unikalne nazwy znaczników.
konfiguracja My nHibernate wygląda następująco:
<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: inny obiekt o tej samej wartości identyfikatora był już związany z sesją tagu: 1, jednostki: 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
...
Wszelkie myśli o tym, co robię źle i jak to naprawić?
Wierzę, że problem ma charakter wewnętrzny i pochodzi od sposobu, można uzyskać listę istniejących tagów do porównaj nowy z i jak przypisujesz istniejący do nowego obiektu BlogPost. Dobrym pomysłem byłoby opublikowanie kodu BlogRepository.Save(); metoda, w której to wszystko się dzieje, abyśmy mogli wykryć problem. – tolism7