Должен ли я загружать/получать объект перед SaveOrUpdate в Nhibernate?

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

***** - ОБНОВИТЬ - ***

Мой контроллер получает пользователя (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);
        }

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

ОБНОВЛЕНИЕ

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

РЕШЕНИЕ

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

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

Как объяснил Айенде здесь, Nhibernate пытается обновить моя сущность с таким запросом:

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

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

User = this._UserRepository.Update(user);

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


person LeftyX    schedule 26.01.2011    source источник
comment
попробуйте загрузить объект и после повторного сопоставления (я знаю, что вы этого не хотите), просто попробуйте это и сообщите нам, работает ли он таким образом.   -  person Omu    schedule 27.01.2011
comment
Я предполагаю, что моя проблема связана с версией. У меня есть ‹имя версии=тип версии=System.Int32 unsaved-value=0› ‹имя столбца=версия не-null=true /› ‹/версия› определено в моем сопоставлении. Думаю, мне нужно найти лучший способ сделать это.   -  person LeftyX    schedule 27.01.2011


Ответы (2)


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

person Diego Mijelshon    schedule 26.01.2011
comment
Боюсь, я не могу этого сделать, потому что если я попытаюсь сохранить свою сущность, я получу это сообщение: другой объект с тем же значением идентификатора уже был связан с сеансом: caedb8a4-abce-4c6f-b171-9e7200cc7a37, сущности: BpReminders.Domain.User - person LeftyX; 26.01.2011
comment
Это означает, что объект уже загружен. Почему тогда вы не обновляете уже загруженный объект? - person Diego Mijelshon; 26.01.2011
comment
жаль, что это была ошибка. Что я сейчас делаю, так это загружаю сущность из репозитория и объединяю ее с той, что получена из контроллера. Я все еще получаю сообщение об ошибке, когда строка была обновлена ​​или удалена другой транзакцией (или сопоставление несохраненных значений было неправильным), когда я пытаюсь вставить. Я обновлю свой первоначальный вопрос дополнительной информацией. - person LeftyX; 27.01.2011

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

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

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

person Darin Dimitrov    schedule 26.01.2011
comment
Спасибо Дэринг. Я предполагаю, что мне нужно использовать пустой Guid (00000000-0000-0000-0000-0000000000000), если мой идентификатор имеет тип Guid, верно? - person LeftyX; 26.01.2011
comment
@vandalo, попробуйте это: unsaved-value="00000000-0000-0000-0000-000000000000" (не проверено). - person Darin Dimitrov; 26.01.2011
comment
Еще раз спасибо. Что бы вы сделали, в любом случае? Должен ли я скорее загружать объект из БД и заполнять каждое поле новым объектом на случай, если я пытаюсь обновить? Есть ли передовой опыт? В очередной раз благодарим за помощь. - person LeftyX; 26.01.2011