Estoy escribiendo un motor de blog como ejercicio de aprendizaje. Sé que hay muchos motores de blogs por ahí, pero tengan paciencia ...Cómo evitar NHibernate.NonUniqueObjectException
Tengo una entidad BlogPost que tiene una propiedad Etiquetas que son una IList de etiquetas asociadas. El método BlogPost.SetTags (cadena) divide la cadena, crea nuevos objetos Tag con el nombre de etiqueta especificado y los agrega a la lista. Lo mismo para BlogPost.AddTag (string tagName).
Lo que me gustaría que sucediera es que cuando llamo a BlogPost.AddTag ("foo") donde ya existe una entidad de etiqueta llamada "foo" y persiste en la base de datos, nHibernate se da cuenta de eso y conecta la publicación con la etiqueta existente.
En el método BlogRepository.Save(), compruebo si cada etiqueta en la lista de etiquetas ya existe. Si no, lo guardo con una llamada a TagRepository.Save (tag);
El problema es, en el código de ejemplo siguiente, estoy recibiendo un error "NHibernate.NonUniqueObjectException: un objeto diferente con el mismo valor de identificador ya estaba asociado con la sesión: la etiqueta 1, de entidad: CMS.Core. Model.Tag "cuando intento persistir un objeto BlogPost usando una etiqueta existente. Cuando insisto en un objeto BlogPost que solo usa nuevas etiquetas, se crean y todo está bien.
Nota También estoy usando TagName como clave principal en la base de datos para la tabla bp_Tags. Parecía superfluo usar un entero o GUID PK cuando la tabla solo almacena nombres únicos de Etiqueta.
configuración de Mi NHibernate parece:
<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: un objeto diferente con el mismo valor de identificador ya estaba asociado con la sesión: etiqueta 1, de entidad: 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
...
Alguna idea de lo que estoy haciendo mal y cómo solucionarlo?
Creo que el problema es interno y proviene de la forma en que recibe la lista de etiquetas existentes para compara el nuevo con, y cómo asignar uno existente al nuevo objeto BlogPost. Sería una buena idea publicar el código de BlogRepository.Save(); método donde todo esto sucede para que podamos detectar el problema. – tolism7