Hey guys,

I've hit a snag while working with NHibernate and I'm not sure if the 
problem is incredibly trivial or incredibly complex. Naturally, I'm hoping 
for the former. Here's an explanation of my scenario:

I have an immutable entity, Video, which has an assigned ID:

<class name="Video" table="[Videos]" lazy="false" mutable="false">
  <id name="Id" length="11" type="String">
    <generator class="assigned"></generator>
  </id>

  <property name="Title" not-null="true" />
  <property name="Duration" not-null="true" />
  <property name="Author" not-null="true" /></class>

I then create and save two detached Video entities which have the same ID. 
NHibernate throws a NonUniqueObjectException when I attempt to save the 
second Video. Here's a failing test case:

public void CreateItem_VideoAlreadyExists_ItemCreatedVideoNotUpdated(){
    //  Save this Video before continuining so that it exists before adding the 
PlaylistItem.
    string randomVideoId = Guid.NewGuid().ToString().Substring(0, 11);
    var videoNotInDatabase = new Video(randomVideoId, "Video", 999, "Author");
    VideoManager.Save(videoNotInDatabase);

    //  Change the title for videoInDatabase to check that cascade-update does 
not affect title. Videos are immutable.
    const string videoTitle = "A video title";
    var videoInDatabase = new Video(randomVideoId, videoTitle, 999, "Author");

    //  Create a new PlaylistItem and write it to the database.
    string title = videoInDatabase.Title;
    var playlistItem = new PlaylistItem(title, videoInDatabase);

    Playlist.AddItem(playlistItem);
    PlaylistManager.SavePlaylistItem(playlistItem);

    //  Remove entity from NHibernate cache to force DB query to ensure 
actually created.
    NHibernateSessionManager.Instance.Clear();

    //  Ensure that the Video was NOT updated by comparing the new title to the 
old one.
    Video videoFromDatabase = VideoDao.Get(randomVideoId);
    Assert.AreNotEqual(videoFromDatabase.Title, videoTitle);

    //  Ensure that the PlaylistItem was created.
    PlaylistItem itemFromDatabase = PlaylistItemDao.Get(playlistItem.Id);
    Assert.NotNull(itemFromDatabase);

    //  Pointers should be self-referential with only one item in the Playlist.
    Assert.AreEqual(itemFromDatabase.NextItem, itemFromDatabase);
    Assert.AreEqual(itemFromDatabase.PreviousItem, itemFromDatabase);}

This test case fails on "PlaylistManager.SavePlaylistItem" which is just a 
transaction wrapper for calling NHibernate's ISession.Save.

I understand why (and my options, such as Merge, Evict, or Refresh) but I 
feel like an option is missing. My Video entity is immutable, so it cannot 
be updated. NHibernate already knows about the Video because it is in its 
cache, so it cannot be inserted. As such, even though NHibernate throws a 
NonUniqueObjectException… in reality, no operation can occur on the entity. 
I have been unable to find a way to express this to NHibernate.

I am opposed to having to refresh the Video entity because it is the child 
of a large hierarchy of parent entities. Iterating to the bottom of the 
hierarchy for each entity in the collection, just to call Refresh on a 
Video, seems like an extremely bad design decision.

I understand that if I used a Versioning system that NHibernate would be 
able to determine that the two entities are unique. However, I do not wish 
for them to be treated as such. I only want one Video with a given ID to be 
written to my table.

Full details can be found here: 
http://stackoverflow.com/questions/17396362/nonuniqueobjectexception-thrown-after-client-attempts-to-save-the-same-item-twic
  

Do I have an architectural flaw? Am I missing a simple keyword? Or is this 
'hard' for other reasons?

Thanks for taking the time to read. Cheers,

Sean Anderson

-- 
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/nhusers.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to