7

в моем приложении ASP.NET MVC Я отделил модель домена от модели представления.
Я преобразовываю свою сущность в объект viewmodel, поэтому я могу «прокормить» мои представления только необходимыми данными (для этой цели я использовал значение инжектор).
Во время сохранения мой контроллер возвращает объект viewmodel, преобразует его в объект модели домена и пытается сохранить его с помощью SaveOrUpdate. Я заметил, что если я пытаюсь обновить существующую запись, Nhibernate рассматривает ее как новый объект и заставляет INSERT, даже если у моего объекта есть правильный идентификатор.
Я не загрузил (Get/Load) объект до причины, я бы хотел избежать повторной карты всех полей.
Есть ли что-нибудь, что я делаю неправильно? Каков наилучший способ достичь этого?Должен ли я загрузить/получить объект перед SaveOrUpdate в Nhibernate?

***** - ОБНОВЛЕНИЕ - ***

Мой контроллер получает пользователь (ViewModel), проверяет его и пытается сохранить его через слой службы как объект:

public ActionResult Edit(Guid id, Models.User User) 
{ 
... 
var user = new Domain.User(); 
user.InjectFrom(User); 
user.SetId(id); 

user = this._SecurityService.SaveUser(user); 

} 

Это услуга:

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); 
     } 

у меня есть беспокойство по поводу того, что я должен преобразовать мой ViewModel/юридическое лицо так много раз. Теперь, когда я пытаюсь сохранить нового пользователя, я получил это сообщение: Строка была обновлена ​​или удалена другой транзакцией (или неверное сопоставление неверно)
Возможно, это в некотором роде связано с тем, что мне рассказывал Дарин.
Есть ли лучшие способы сделать то, что я пытаюсь сделать?

UPDATE

Я заметил, что ошибка «строка была обновлена ​​или удалена ...» вызван тем, что у меня есть версия, определенная для моих отображений. Я могу понять, что мне нужно иметь Id и версию , соответствующую объекту, который я хочу обновить.
Я хотел бы понять, как другие люди делают эти вещи с помощью DDD + ASP.NET MVC + NHibernate ???

РЕШЕНИЕ

Все мои объекты имеют версии определены (я забыл сказать, извините):

<version name="Version" type="System.Int32" unsaved-value="0"> 
    <column name="Version" not-null="true" /> 
</version> 

Как Ayende объяснил here, Nhibernate пытается обновить свою сущность с запросом, как это :

UPDATE Table SET field1 = 'bla', Version = (y+1) WHERE id = x AND Version = y 

где y должна быть версия моего объекта. Поскольку я не заполнял свою сущность версией, она генерирует исключение StaleObjectException.
Я добавил поле версии в мою модель просмотра. Я сохраняю его в скрытом поле моего представления вместе с идентификатором.
Теперь мой контроллер получает модель с идентификатором и версией. я впрыснуть эти поля в моей области лица и пусть хранилище сохранить его (я не перезарядить мою сущность):

User = this._UserRepository.Update(user); 

Если я получаю StaleObjectException исключение это означает, что кто-то обновил строку DB и я предоставил пользователю некоторую обратную связь.

+0

попробуйте загрузить объект и после его повторной карты (я знаю, что вы этого не хотите), просто попробуйте это и сообщите нам, если он работает таким образом – Omu

+0

Я думаю, моя проблема с версией. Я got , определенный в моем сопоставлении. чтобы найти лучший способ сделать это. – LeftyX

ответ

0

Поскольку у вас уже есть идентификатор и, следовательно, знаете, что это обновление, используйте session.Update вместо SaveOrUpdate.

+0

Я боюсь, что не могу сделать это, если попытаюсь сохранить свою сущность. Я получаю это сообщение: другой объект с тем же значением идентификатора уже был связан с сеансом: caedb8a4-abce-4c6f-b171-9e7200cc7a37, объекта : BpReminders.Domain.User – LeftyX

+0

Это означает, что объект уже загружен. Почему вы не обновляете уже загруженный объект? –

+0

извините, что это была ошибка. Теперь я загружаю объект из репозитория и объединяю его с получателем, полученным от контроллера. Я все равно получаю сообщение об ошибке «Строка была обновлена ​​или удалена другой транзакцией (или неправильное сопоставление несоответствующих значений)», когда я пытаюсь вставить. Я обновлю свой первоначальный вопрос с дополнительной информацией. – LeftyX

4

Для работы SaveOrUpdate для работы, как ожидается, вам необходимо явно указать атрибут unsaved-value на картинке <id>. Так, например, вы бы:

<id unsaved-value="0" ... 

, а затем выдать SaveOrUpdate вызов на модели, которая имеет свойство Id присвоенное значение, отличное чем 0 и он собирается UPDATE вместо INSERT. Поэтому, чтобы ответить на ваш вопрос, нет, вам не нужно вручную выдавать SELECT до UPDATE. SaveOrUpdate должен делать это за кулисами.

+0

Спасибо Daring. Я предполагаю, что я должен использовать пустой Guid (00000000-0000-0000-0000-000000000000), если мой идентификатор типа Guid, правильно? – LeftyX

+0

@vandalo, попробуйте следующее: 'unsaved-value =" 00000000-0000-0000-0000-000000000000 "' (untested) –

+0

Спасибо, опять же, что бы вы сделали? В любом случае? Должен ли я загружать объект из базы данных и заполнять каждое поле новым объектом в ca se Я пытаюсь обновить? Есть ли лучшие практики? В очередной раз благодарим за помощь. – LeftyX