Record Updated After TryUpdateModel Fails

Topics: Writing modules
Feb 26, 2012 at 1:06 AM
Edited Feb 26, 2012 at 1:10 AM

I'm seeing something pretty strange - I have a module that does data access. It uses NHibernate for data access but I'm actually not creating a ContentPart, just some functionality in a module that is hosted inside an Orchard site.

I have an action for updating a record, and in the method I call TryUpdateModel, if it succeeds I call an update method in a service, which in turn calls the Update method on my IRepository. That works like I would expect.

When the TryUpdateModel validation fails and returns false I do not call the update method method on my service, but the database gets updated anyway. I've traced through it in the debugger and the call to update definitely does not run in my service or in Orchard.Data.Repository, but I'm tracing the database calls and sure enough the SQL update comes through.

Can someone explain this? I'm thinking there's something going on in the Orchard Repository code that runs the update automatically?



Feb 26, 2012 at 3:34 AM

Yes, nHibernate tracks changes and the ambient transaction will be committed unless you abort it explicitly.

Feb 26, 2012 at 4:44 AM

And the fact that the change is made even without me calling Update, is that done automatically when I call TryUpdateModel? If so is that standard MVC behaviour or something that is added by Orchard?

Feb 26, 2012 at 5:32 AM
Edited Feb 26, 2012 at 5:33 AM

That is added by Orchard. As is the ambient transaction. And nHibernate.

Feb 26, 2012 at 5:46 AM

How does Orchard or NHibernate know to automatically save the Model's changes? And how would sncodeplex get it to work the way he expects -- prevent the saving when his TryUpdateModel fails? 

Feb 26, 2012 at 5:51 AM
Edited Feb 26, 2012 at 5:51 AM

The objects that you manipulate are not instances of your record classes. Rather, they are dynamic proxies derived from them, where tracking code has been added. That's how it knows what to save. To prevent from saving, simply rollback the transaction. Or throw if that's more appropriate.

Feb 26, 2012 at 7:00 AM

I guess the question though is why, if TryUpdateModel fails (returns false), do I need to rollback, shouldn't that mean those proxies know not to save. I can see that one TryUpdateModel shouldn't necessarily rollback the entire transaction, but it seems like if it is failing then the save of that specific model shouldn't happen?

Feb 26, 2012 at 7:51 PM

Because TryUpdateModel has nothing to do with database persistence. It just happens that you are using it on an object that has database persistence. Maybe you shouldn't.