我正在写一个博客引擎作为学习练习.我知道那里有很多博客引擎,但请耐心等待......
我有一个BlogPost实体,它有一个属性标签,它是与之关联的标签的IList.BlogPost.SetTags(string)方法拆分字符串,使用指定的标记名称创建新的Tag对象,并将它们添加到列表中.BlogPost.AddTag(字符串tagName)也是如此.
我想要发生的是,当我调用BlogPost.AddTag("foo"),其中一个名为"foo"的标签实体已经存在并且在数据库中持久存在时,nHibernate只是意识到这一点,并用现有标签连接帖子.
在BlogRepository.Save()方法中,我检查标签列表中的每个标签是否已经存在.如果没有,我通过调用TagRepository.Save(tag)保存它;
问题是,在下面的示例代码中,我收到一个错误"NHibernate.NonUniqueObjectException:具有相同标识符值的另一个对象已经与会话关联:标记1,实体:CMS.Core.Model.Tag"当我尝试使用现有标记持久保存BlogPost对象时.当我坚持只使用新标签的BlogPost对象时,它们就被创建了,一切都很好.
注意我还使用TagName作为bp_Tags表的数据库中的主键.当表只存储唯一的Tag名称时,使用整数或GUID PK似乎是多余的.
我的nHibernate配置如下:
<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>
Run Code Online (Sandbox Code Playgroud)
NHibernate.NonUniqueObjectException:具有相同标识符值的不同对象已与会话关联:标记1,实体: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
Run Code Online (Sandbox Code Playgroud)
...
关于我做错了什么以及如何解决它的任何想法?
由于TagName是ID,因此您正在运行NHibernate的身份映射.它的身份映射已经知道具有相同ID的对象,因此它会为您提供该异常.
您可能想要尝试一些内容,以查看该会话中是否已存在该标记,如果存在,则将该现有标记与第二篇文章相关联.
Psuedo-code示例:
var tag = session.Get<Tag>("Tag 1");
if (tag != null)
{
post.AddTag(tag);
}
else
{
post.AddTag(new Tag("Tag 1"));
}
Run Code Online (Sandbox Code Playgroud)
此博客文章将为您提供详细说明: NHibernate - 跨会话操作
归档时间: |
|
查看次数: |
13065 次 |
最近记录: |