Do I have to Load/Get an entity before SaveOrUpdate in Nhibernate?
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.
由于您已经拥有一个Id,因此知道这是一个更新,请使用session.Update
而不是SaveOrUpdate
。
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.
上一篇: GLSL