views:

30

answers:

1

Hi,

I'm witnessing some strange behaviour from Fluent nHibernate. I have two objects involved in this problem: a "Page" object and a "Metadata" object. A Page can have multiple Metadata objects attached, and the mapping is done thus:

'in PageMap
HasMany(Function(x) x.MetaData).Cascade.All()
'in MetaDataMap
References(Function(x) x.Page)

The problem occurs on the save process. When I want to save changes to the page object, I get the existing page object, run through the list of changes, then use Session.Update(Page) to save the values. The odd behaviour is that the data does save, but the page Metadata is saved twice: once as expected, and another time with page_id of null. What's stranger though is that this happens even when I comment out the Update command - so it's not actually the update that's causing the data to save!

Stepping through the code and watching the data I traced the error to the point where I'm using nHibernate to get a Page object to use its details. So, before I call this method, the database is showing no Metdata changes at all. Afterward, I can't see the DB (it's busy) but the page that's returned has any added metadata. The get method looks like this:

Public Function GetById(ByVal Id As Integer) As Cms.DataTransferObjects.Page Implements IPageManager.GetById
    Dim session As ISession = NHibernateSessionManagerStore.Instance.GetSession()
    Dim results As Cms.DataTransferObjects.Page

    results = session.CreateCriteria(Of DataTransferObjects.Page)() _
        .Add(Expression.Like("Id", Id)) _
        .UniqueResult(Of DataTransferObjects.Page)()

    Return results
End Function

So there's obviously nothing there that's saving the data.

Can anyone shed any light on this? It's driving me berserk!

Cheers, Matt

+1  A: 

You don't need to call Update when the instance is already in the session. NHibernate is clever enough to find all the changes made on the objects and store them to the database. To put an instance into the session, you usually use a query to get existing objects, or Save to persist a new instance. Update is only useful for detached instances.

Writing the memory state to the database is called Flushing. NH flushes before committing, but also before queries, to make sure that the query is executed on actual data (so if you set a property to "A", you could immediately make a query which filters this property by "A" and you'll get your instance).

I don't know why NH saves a null foreign key. Are you setting the foreign key to null somewhere? Are you trying to "reuse" your instance for something else?

Stefan Steinegger
Thanks for this - very helpful explanation. As it turns out I was creating new orphaned objects elsewhere in the code, and was being confused because they weren't being committed to the DB right away. I doubt I would have spotted this without your answer :)
Matt Thrower