Sean Anderson
Sean Anderson

Reputation: 29301

Entity with client-generated ID. Should I have a separate property for NHibernate's ID?

I have an object of type Video. I am storing Videos in my database, but I want each video entry to be unique. Uniqueness is determined by an 11-digit string provided by the client.

As such, I've generated this Video.hbm.xml file:

<?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>

I have no intention of deleting or updating any entries to this table. So, I've tagged my class as immutable.

Now, I thought this was a pretty good way of going about things, but I am experiencing issues with cascade-updating from a parent object. Because my ID is generated client-side, and I do not leverage a second identifier, NHibernate is unable to reliably determine whether a Video needs to be Inserted or Updated (note that it should never update due to being immutable.)

Something like:

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);

where PlaylistItem's hbm.xml references Video as:

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

The above code generates a NonUniqueObjectException. This is because the VideoManager works with the Video in one session, closes it, then PlaylistManager re-references the same Video in a new Session, but NHibernate can't accomodate because it doesn't have good IDs to go off of.

Removing the option of cascade="save-update" fixes the issue, but then I don't get the benefit of having my Video object created implicitly in the database by NHibernate. Instead, I would have to manually save the Video object and, afterwards, save the PlaylistItem object. This is clearly not ideal.

So, I'm wondering -- should I be assigning a GUID to my Video object? If so, how can I enforce the fact that I only wish to have unique Video entries in my table where uniqueness is defined by the 11 digit string ID?

Let me know if I can provide any more information to make this more clear.

Upvotes: 0

Views: 434

Answers (1)

Tamim Al Manaseer
Tamim Al Manaseer

Reputation: 3724

First of all modify your ID section in you video.hbm.xml to have an "assigned" generator

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

That tells nhibernate that ur IDs are manually generated from the client.

Also having ur same object being manipulated by multiple session will cause consistency errors. So either use a unique session for your batch of actions or make sure ur object is properly tracked in all sessions by using session.Merge

Upvotes: 2

Related Questions