views:

71

answers:

3

I have the following mapping:

<!-- WidgetConfiguration -->
<class name="MyProject.WidgetConfiguration, MyProject" table="WidgetConfigurations">
  <id name="Id" column="Id" type="Int64">
    <generator class="native" />
  </id>

  <property name="Name" column="ConfigurationName" />

  <map name="Widgets" table="WidgetConfigurationPositions" cascade="all" lazy="false" fetch="select" inverse="true">
    <key column="WidgetConfigurationId" />
    <index column="TargetId" type="string" />
    <one-to-many class="MyProject.WidgetPlacement" />
  </map>
</class>
<!-- End WidgetConfiguration -->

<class name="MyProject.WidgetPlacement, MyProject" table="WidgetConfigurationPositions">
  <id name="Id" column="Id" type="Int64">
    <generator class="native" />
  </id>

  <many-to-one name="Widget" class="MyProject.Widget, MyProject" column="WidgetId" lazy="false" />
  <property name="Target" column="TargetId" not-null="true" />

  <map name="Options" table="PlacedWidgetOptions" cascade="all" lazy="false" fetch="select">
    <key column="WidgetConfigurationPositionId"/>
    <index column="OptionName" type="string" />
    <element column="OptionValue" type="string" />
  </map>
</class>

And, I have the following bit of code:

public override void Update(WidgetConfiguration obj)
{
 using (var session = GetSession())
 {
  var tx = session.BeginTransaction();
  session.Update(obj);
  tx.Commit();

  //session.Evict(obj);
 }
}

I can Save a WidgetConfiguration just dandy, but trying to UPDATE a WidgetConfiguration, NHibernate actually performs an insert! Here is the session from my NHibernate Profiler.

begin transaction with isolation level: Unspecified

INSERT INTO WidgetConfigurations
           (ConfigurationName)
VALUES     ('dashboard' /* @p0 */)
select SCOPE_IDENTITY()

INSERT INTO WidgetConfigurationPositions
           (WidgetId,
            TargetId)
VALUES     (1 /* @p0 */,
            'row1-column1' /* @p1 */)
select SCOPE_IDENTITY()

UPDATE WidgetConfigurationPositions
SET    WidgetId = 1 /* @p0 */,
       TargetId = 'row1-column2' /* @p1 */
WHERE  Id = 356 /* @p2 */

commit transaction

I have no idea why this would be happening and Google is not being very helpful. Anyone have any ideas?

A: 

My guess is that your problem is caused by retrieving the object in one NH session and updating it in another.

Either keep the NH session open throughout the request, or try to attach (Lock() ?) the object to the updating NH session.

devio
How does nh figure out which operation to do on a, say, SaveOrUpdate? I always assumed that if the ID field was set then it would update.
Brad Heller
I thought so too but this is a supported usage: http://knol.google.com/k/fabio-maulo/nhibernate-chapter-9-manipulating/1nr4enxv3dpeq/12#9%282E%294%282E%29%28C2%29%28A0%29Updating_objects
Jamie Ide
+2  A: 

Try setting the unsaved-value attribute:

<id name="Id" column="Id" type="Int64" unsaved-value="0">
    <generator class="native" />
</id>

What is the type of the ID column? If it's long? then unsaved-value should be null. You shouldn't need to set this but it's the first thing I would try.

Jamie Ide
+1  A: 

Are you remembering to override your Equals() and GetHashCode()? Since you are detaching and then re-attaching these methods will come into play.

I'd recommend picking up NHibernate In Action and reading about persistence lifecycle :)

ShaneC