in my ASP.NET MVC application I've separated the domain model from the view model.
I transform my entity in a viewmodel object so I can "feed" my views with only the data needed (I used valueinjecter for this purpose).
During the save process my controller gets back the viewmodel object, transforms it into a domain model entity and try to persist it with SaveOrUpdate.
I've noticed that if I try to update an existing record, Nhibernate considers it as a new object and forces an INSERT, even if my entity has a proper ID.
I haven't loaded (Get/Load) the entity before cause I would like to avoid to re-map all the fields again.
Is there anything I am doing wrong? What's the best way to achieve that?
***** - UPDATE - ***
My controller receives a User (ViewModel), validates it and tries to save it through a service layer as an entity:
public ActionResult Edit(Guid id, Models.User User)
{
...
var user = new Domain.User();
user.InjectFrom(User);
user.SetId(id);
user = this._SecurityService.SaveUser(user);
}
This is the service:
public Domain.User SaveUser(Domain.User User)
{
bool Result = false;
if (this._ValidationEngine.IsValid(User))
{
using (_UnitOfWork)
{
if (User.Code != Guid.Empty)
{
var user = this._UserRepository.Load(User.Code);
user.InjectFrom(User);
User = this._UserRepository.Update(user);
}
else {
User = this._UserRepository.Save(User);
}
Result = _UnitOfWork.Commit();
}
}
return (User);
}
I've got a concern about the fact that I have to transform my viewmodel/entity so many times. Now when I try to save a new User I got this message: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
Probably this is in some ways related to what Darin was telling me.
Are there any better ways to do what I am trying to do?
UPDATE
I've noticed that the error "Row was updated or deleted..." is caused by the fact that I have a version defined for my mappings. What I can understand is I need to have the Id and the version matching the entity I want to update.
I would like to understand how other people do these things with DDD + ASP.NET MVC + NHibernate ???
SOLUTION
All my entities have a version defined (I forgot to say, sorry):
<version name="Version" type="System.Int32" unsaved-value="0">
<column name="Version" not-null="true" />
</version>
As Ayende explained here, Nhibernate tries to update my entity with a query like this:
UPDATE Table SET field1 = 'bla', Version = (y+1) WHERE id = x AND Version = y
where y should be the version of my entity. Since I wasn't populating my entity with a version, it would generate an exception StaleObjectException.
I've added a version field to my viewmodel. I save it in a hidden field of my view together with the id.
My controller now receives a viewmodel with an Id and a version.
I inject these fields in my domain entity and let the repository save it (I don't reload my entity):
User = this._UserRepository.Update(user);
If I get a StaleObjectException exception it means that someone else has updated the DB row and I'll provide the user with some feedback.
For SaveOrUpdate
to work as expected you need to explicitly specify the unsaved-value
attribute on your <id>
mapping. So for example you would have:
<id unsaved-value="0" ...
and then issue a SaveOrUpdate
call on a model which has the Id property assigned to a value different than 0
and it is going to UPDATE
instead of INSERT
. So to answer your question, no, you don't need to manually issue a SELECT
before UPDATE
. SaveOrUpdate
should do this behind the scenes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With