Figured it out...
<composite-id>
<key-property name="Id" />
<key-many-to-one name="Playlist" column="PlaylistId"/>
</composite-id>
On Tuesday, April 2, 2013 10:47:29 PM UTC+1, Sean Anderson wrote:
>
> I'm hoping not to argue semantics and "you should not use a composite key"
> with this post. I understand the implications of composite key use, but
> believe it to be best suited for my task at hand.
>
> I have the following in "PlaylistItem.hbm.xml:"
>
> <?xml version="1.0" encoding="utf-8" ?><hibernate-mapping
> xmlns="urn:nhibernate-mapping-2.2" assembly="Streamus"
> namespace="Streamus.Backend.Domain">
>
> <class name="PlaylistItem" table="[PlaylistItems]" lazy="false" >
> <composite-id>
> <key-property name="Id" />
> <key-property name="PlaylistId"/>
> </composite-id>
>
> <property name="Title" not-null="true" />
>
> <many-to-one name="Playlist" column="PlaylistId"/>
> </class>
> </hibernate-mapping>
>
> which corresponds with the following class:
>
> [DataContract]public class PlaylistItem{
> [DataMember(Name = "playlistId")]
> public Guid PlaylistId
> {
> get { return Playlist.Id; }
> set { Playlist.Id = value; }
> }
>
> public Playlist Playlist { get; set; }
>
> [DataMember(Name = "id")]
> public Guid Id { get; set; }
>
> // Store Title on PlaylistItem as well as on Video because user might
> want to rename PlaylistItem.
> [DataMember(Name = "title")]
> public string Title { get; set; }
>
> public PlaylistItem()
> {
> // Id shall be generated by the client. This is OK because it is
> composite key with
> // PlaylistId which is generated by the server.
> Id = Guid.Empty;
> Title = string.Empty;
> }
>
> private int? _oldHashCode;
> public override int GetHashCode()
> {
> // Once we have a hash code we'll never change it
> if (_oldHashCode.HasValue)
> return _oldHashCode.Value;
>
> bool thisIsTransient = Equals(Id, Guid.Empty);
>
> // When this instance is transient, we use the base GetHashCode()
> // and remember it, so an instance can NEVER change its hash code.
> if (thisIsTransient)
> {
> _oldHashCode = base.GetHashCode();
> return _oldHashCode.Value;
> }
> return Id.GetHashCode();
> }
>
> public override bool Equals(object obj)
> {
> PlaylistItem other = obj as PlaylistItem;
> if (other == null)
> return false;
>
> // handle the case of comparing two NEW objects
> bool otherIsTransient = Equals(other.Id, Guid.Empty);
> bool thisIsTransient = Equals(Id, Guid.Empty);
> if (otherIsTransient && thisIsTransient)
> return ReferenceEquals(other, this);
>
> return other.Id.Equals(Id);
> }}
>
>
> This clearly generates an exception with NHibernate because the property
> "PlaylistId" is referenced through the composite key definition as well as
> in the many-to-one definition. I am obstinate about using PlaylistId as
> part of the composite key. I would also like to leverage as much of
> NHibernate's built-in capabilities in order to preserve data integrity.
>
> I've implemented the following as a work-around, but I am not happy with
> my change. I am not using NHibernate's ability to automatically dehydrate
> Playlist when loading a PlaylistItem:
>
> public Guid PlaylistId{
> get
> {
> return Playlist == null ? Guid.Empty : Playlist.Id;
> }
> set
> {
> if (Playlist == null || Playlist.Id != value)
> {
> Playlist = new PlaylistDao().Get(value);
> }
> }}
>
> in addition to this change, I remove <many-to-one name="Playlist" column=
> "PlaylistId"/>
>
> This works as expected. Whenever NHibernate dehydrates the PlaylistId via
> the composite key, PlaylistItem's Playlist property is set. However, the
> code obviously smells. I am wondering -- do I have any options here? Or, is
> this an unsupported scenario in NHibernate?
>
> Thanks
>
--
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.