Why does NHibernate delete then insert composite-elements on select?

nhibernate

Solution

I think you need to override Equals() and GetHashCode() on Comment. NHibernate doesn't have an ID to go on for entity equality so you have to define what makes a comment entity equal to another comment.

Could be wrong :)

Edit

From nhibernate.info (8.2)

Note: if you define an ISet of composite elements, it is very important to implement Equals() and GetHashCode() correctly.

And an example of implementing Equals / GetHashCode from nhibernate.info (4.3)

public class Cat
{    
    ...
    public override bool Equals(object other)
    {
        if (this == other) return true;

        Cat cat = other as Cat;
        if (cat == null) return false; // null or not a cat

        if (Name != cat.Name) return false;
        if (!Birthday.Equals(cat.Birthday)) return false;

        return true;
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int result;
            result = Name.GetHashCode();
            result = 29 * result + Birthday.GetHashCode();
            return result;
        }
    }    
}

Problem

Can someone explain this little mystery to me about how NHibernate handles composite elements. I have classes that look like this; ``` public class Blog { public virtual int Id { get; private set; } public virtual ISet<Comment> Comments { get; set; } } public class Comment { public virtual string CommentText { get; set; } public virtual DateTime Date { get; set; } } ``` and mappings like this; ``` <class name="Blog" table="blog"> <id name="Id" column="id" unsaved-value="0"> <generator class="hilo"/> </id> <set name="Comments" table="blog_comments"> <key column="blog_id" /> <composite-element class="Comment"> <property name="CommentText" column="comment" not-null="true" /> <property name="Date" column="date" not-null="true" /> </composite-element> </set> </class> ``` However when i perform a select like this; ``` using (ITransaction transaction = session.BeginTransaction()) { Blog blog = session.CreateCriteria(typeof(Blog)) .SetFetchMode("Comments", FetchMode.Eager) .Add(Expression.IdEq(2345)) .UniqueResult(); transaction.Commit(); } ``` NHibernate issues a select with a join to get the blog with posts BUT then deletes all comments and then inserts the comments! Why is it doing this? If i do not use a transaction then it will ONLY perform the select and not the DELETE and INSERT as I would expect. What am I missing? I am using NHibernate 2.0

Original source