The architectural flaw would be this:

var videoInDatabase = new Video(randomVideoId, videoTitle, 999, "Author");


Newing up something that you know is in the database.

var videoInDatabase = VideoDao.Get(randomVideoId);

or (given a modification to the Dao, which uses Load instead of Get)

var videoInDatabase = VideoDao.GetReference(randomVideoId);

if you want to avoid the database roundtrip.

/G


2013/7/1 Tyler Burd <[email protected]>

> If you map the Video class as “lazy”, and simply do a
> Session.Load(yourVideoId), NH will not actually fetch the video from the
> database; it will fetch it from the session cache (if the entity has
> already been loaded), or just give you a simple proxy.  Even with
> immutables, NHibernate does not like it when multiple instances have the
> same id.****
>
> ** **
>
> *From:* [email protected] [mailto:[email protected]] *On
> Behalf Of *Sean Anderson
> *Sent:* Monday, July 01, 2013 11:16 AM
> *To:* [email protected]
> *Subject:* [nhusers] NonUniqueObjectException when working with an
> immutable entity. Possible to suppress?****
>
> ** **
>
> 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.
>
>  ****
>
> --
> 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.
>
>
>

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