Having a NHibernate entity:
public class Employee
{
public virtual int Id { get; set; }
public virtual int Idc { get; set; }
public virtual int Ide { get; set; }
.
. other properties
.
}
with Id mapped as:
<id name="Id" unsaved-value="0">
<generator class="sequence">
<param name="sequence">employee_id_seq</param>
</generator>
</id>
If I populate all properties of a new Employee except Id and then call session.Merge() it just creates another row with all properties identical to the original row except Id instead of merging with the existing employee.
Is it possible to do instead an update at database level on the row corresponding to those properties?
Idc + Ide together are unique so it should be possible to identify the row to be merged.
Thanks for your help!
NHibernate session maintains an identity map for all currently loaded (persisted) objects. Identity map uses the entity id as the key. In your case, your
Idis a simpleintvalue and since it’s equal to0(by default) for newly created object,session.Merge()can’t find the matching persistent entity in session. Instead, a new row is added to database.Read Ayende’s post about cross-session operations for more in depth explanation.
In other cases, where you want to have a different notion of entity equality, you would override
Equals()andGetHashCode()methods of your entity – i.e. to compare all properties, but I’m afraid, it won’t help you in this case.Just for the reference, here are some links about
Equals()andGetHashCode()usage:Is there a sample why Equals/GetHashCode should be overwritten in NHibernate?
NHibernate: Reasons for overriding Equals and GetHashCode
Edit
There are two options to update the row at database level:
You could do NHibernate update query, something along these lines:
Also, you could use native SQL to do this:
session.CreateSQLQuery("...").ExecuteUpdate();Or you could load the entity first, update its properties and then save it: