0

我有一个视频类型的对象。我将视频存储在我的数据库中,但我希望每个视频条目都是唯一的。唯一性由客户端提供的 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 将 Video 引用为:

<many-to-one name="Video" column="VideoId" not-null="true" cascade="save-update" />

上面的代码会生成一个 NonUniqueObjectException。这是因为 VideoManager 在一个会话中处理视频,将其关闭,然后 PlaylistManager 在新会话中重新引用相同的视频,但 NHibernate 不能适应,因为它没有好的 ID 可以关闭。

删除 cascade="save-update" 的选项解决了这个问题,但是我没有得到 NHibernate 在数据库中隐式创建我的 Video 对象的好处。相反,我必须手动保存 Video 对象,然后保存 PlaylistItem 对象。这显然不理想。

所以,我想知道——我应该为我的 Video 对象分配一个 GUID 吗?如果是这样,我如何强制执行这样一个事实,即我只希望在我的表中拥有唯一的视频条目,其中唯一性由 11 位字符串 ID 定义?

让我知道我是否可以提供更多信息以使这一点更清楚。

4

1 回答 1

2

首先,修改 video.hbm.xml 中的 ID 部分,使其具有“已分配”生成器

<id name="id" ....>
    <generator class="assigned" />
</id>

这告诉 nhibernate 您的 ID 是从客户端手动生成的。

同样让您的同一个对象被多个会话操作会导致一致性错误。因此,要么为您的批处理操作使用唯一会话,要么使用 session.Merge 确保在所有会话中正确跟踪您的对象

于 2013-06-30T21:56:44.783 回答