Mapping:
<class name="PhoneTypeTest" lazy="false" table="PhoneType">
<cache usage="read-write"/>
<id name ="Id" type="Int32" unsaved-value="0">
<generator class="identity"/>
</id>
<bag name="Resources" table="PhoneTypeResource" lazy="false" cascade="all" inverse="true">
<key column="PhoneTypeId" />
<one-to-many class="PhoneTypeTestResource" not-found="ignore"/>
</bag>
</class>
<class name="PhoneTypeTestResource" lazy="false" table="PhoneTypeResource">
<composite-id class="CCCC.ResourcesCompositeKey, DDDD" name="Id">
<key-property name="OwnerId" column="PhoneTypeId"/>
<key-property name="CultureId"/>
</composite-id>
<property name="Name"/>
</class>
Entities:
public class PhoneTypeTest
{
public PhoneTypeTest()
{
Resources = new List<PhoneTypeTestResource>();
}
public virtual int Id { get; set; }
public virtual IList<PhoneTypeTestResource> Resources { get; set; }
}
public class PhoneTypeTestResource
{
public virtual ResourcesCompositeKey Id { get; set; }
public virtual string Name { get; set; }
}
Unit test:
var ent = new PhoneTypeTest();
ent.Resources.Add(new PhoneTypeTestResource { Id = new ResourcesCompositeKey { CultureId = En, OwnerId = 0 }, Name = "Name" });
Session.Merge(ent);
Session.Flush();
Session.Clear();
SQL generated by nHib:
-- statement #1
INSERT INTO PhoneType
DEFAULT VALUES
select SCOPE_IDENTITY()
-- statement #2
SELECT phonetypet0_.PhoneTypeId as PhoneTyp1_61_0_,
phonetypet0_.CultureId as CultureId61_0_,
phonetypet0_.Name as Name61_0_
FROM PhoneTypeResource phonetypet0_
WHERE phonetypet0_.PhoneTypeId = 0 /* @p0 */
and phonetypet0_.CultureId = 'en' /* @p1 */
-- statement #3
INSERT INTO PhoneTypeResource
(Name,
PhoneTypeId,
CultureId)
VALUES ('Name' /* @p0 */,
0 /* @p1 */,
'en' /* @p2 */)
-- statement #4
ERROR:
Could not synchronize database state with session
SO, as you can see, the problem is that nHib does NOT update child a composite-id after its parent was saved, and the attempt to save children fails. Why?? How can I make nHib to update these ids? Also, if I use SaveOrUpdate() instead Merge(), it works fine!! But I must use merge. Please help!
I ended up manually updating child ids after saving - just another workaround of nHibernate's bug. Do not use composite ids or, even better solution, do not use nHibernate..