Нужно ли загружать / получать объект перед SaveOrUpdate в Nhibernate? - PullRequest
7 голосов
/ 26 января 2011

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

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

Мой контроллер получает пользователя (ViewModel), проверяет его и пытается сохранить его через службуlayer as 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);

}

Это сервис:

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 , это означает, что кто-то ещеобновил строку БД, и я предоставлю пользователю некоторую обратную связь.

Ответы [ 2 ]

4 голосов
/ 26 января 2011

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

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

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

0 голосов
/ 26 января 2011

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

...