我有一个Video类型的对象。我将视频存储在我的数据库中,但我希望每个视频条目都是唯一的。唯一性由客户提供的11位数字符串确定。
因此,我已经生成了这个Video.hbm.xml文件:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Streamus" namespace="Streamus.Domain">
<class name="Video" table="[Videos]" lazy="false" mutable="false">
<id name="Id" length="11" type="String" />
<property name="Title" not-null="true" />
<property name="Duration" not-null="true" />
<property name="Author" not-null="true" />
</class>
</hibernate-mapping>
我无意删除或更新此表的任何条目。所以,我已经将我的课程标记为不可变。
现在,我认为这是处理事情的一种非常好的方式,但我遇到了来自父对象的级联更新问题。因为我的ID是在客户端生成的,而我没有利用第二个标识符,所以NHibernate无法可靠地确定是否需要插入或更新视频(请注意,由于不可变,它永远不会更新。)
类似的东西:
Video video = new Video("s91jgcmQoB0", "Tristam - Chairs", 219, "MeoMix");
new VideoManager().Save(video);
// Create a new PlaylistItem and write it to the database.
string title = video.Title;
PlaylistItem playlistItem = new PlaylistItem(title, video);
Playlist.AddItem(playlistItem);
PlaylistManager.SavePlaylistItem(playlistItem);
其中PlaylistItem的hbm.xml将视频引用为:
<many-to-one name="Video" column="VideoId" not-null="true" cascade="save-update" />
上面的代码生成一个NonUniqueObjectException。这是因为VideoManager在一个会话中使用视频,关闭它,然后PlaylistManager在新的会话中重新引用相同的视频,但NHibernate无法容纳,因为它没有好的ID可以关闭的。
删除cascade =&#34; save-update&#34;的选项修复了这个问题,但是我没有从NHibernate隐藏在数据库中创建我的Video对象的好处。相反,我必须手动保存Video对象,然后保存PlaylistItem对象。这显然不太理想。
所以,我想知道 - 我应该为我的视频对象分配一个GUID吗?如果是这样,我怎么能强制执行这样一个事实,即我只希望在我的表中有唯一性由11位字符串ID定义的唯一视频条目?
如果我能提供更多信息以便更清楚,请告诉我。
答案 0 :(得分:2)
首先修改video.hbm.xml中的ID部分,使其具有“已分配”的生成器
<id name="id" ....>
<generator class="assigned" />
</id>
告诉nhibernate你的ID是从客户端手动生成的。
同一个对象被多个会话操纵也会导致一致性错误。因此,要么为您的一批操作使用唯一会话,要么确保使用session.Merge在所有会话中正确跟踪您的对象