Подтвердить что ты не робот

Как вставить или обновить (или перезаписать) запись с помощью NHibernate?

Мне нужно написать строку в базе данных независимо от того, существует она уже или нет. Перед использованием NHibernate это было выполнено с помощью хранимой процедуры. Процедура будет пытаться обновить, и если никакие строки не будут изменены, она будет отбрасываться на вставку. Это хорошо работает, потому что приложение не заботится о том, существует ли запись.

В NHibernate найденные решения требуют загрузки объекта и его модификации или удаления объекта, чтобы новый можно было вставить. Приложение действительно заботится о том, что запись уже существует. Есть ли способ обойти это?

Имеет ли значение Id?

Назначенный идентификатор

Объект имеет ключевое слово в качестве назначенного идентификатора и является основным ключом в таблице.

Я понимаю, что SaveOrUpdate() вызовет метод Save() или Update(), если это необходимо на основе Id. Используя назначенный идентификатор, это не будет работать, потому что id не является несохраненным значением. Однако вместо этого в качестве индикатора можно использовать поле Version или Timestamp. В действительности это не актуально, поскольку это отражает только то, связан ли объект в памяти с записью в базе данных; он не указывает, существует ли запись в базе данных или нет.

Сгенерированный идентификатор

Если назначенный идентификатор действительно был причиной проблемы, я мог бы использовать сгенерированный идентификатор вместо ключевого слова в качестве первичного ключа. Это позволит избежать проблемы вставки/обновления NHibernate, так как она всегда будет всегда вставляться. Тем не менее, мне по-прежнему необходимо предотвратить дублирование ключевых слов. С уникальным индексом в столбце ключевых слов он все равно будет генерировать исключение для повторяющегося ключевого слова, даже если первичный ключ отличается.

Другой подход?

Возможно, проблема не в NHibernate, а в том, как это моделируется. В отличие от других областей приложения, это больше ориентировано на данные, а скорее объектно-ориентированное. Приятно, что NHibernate упрощает чтение/запись и устраняет хранимые процедуры. Но стремление просто писать без учета существующих значений не вполне соответствует модели модели идентичности объекта. Есть ли лучший способ приблизиться к этому?

4b9b3361

Ответ 1

Я использую

    public IList<T> GetByExample<T>(T exampleInstance)
    {
        return _session.CreateCriteria(typeof(T))
                    .Add(Example.Create(exampleInstance))
                    .List<T>();
    }

    public void InsertOrUpdate<T>(T target)
    {
        ITransaction transaction = _session.BeginTransaction();
        try
        {
            var res=GetByExample<T>(target);
            if( res!=null && res.Count>0 )
                _session.SaveOrUpdate(target);
            else
               _session.Save(target); 
            transaction.Commit();
        }
        catch (Exception)
        {
            transaction.Rollback();
            throw;
        }
        finally
        {
            transaction.Dispose();
        }
    }

но метод FindByExample возвращает все объекты, а не объекты с точным идентификатором, что вы предлагаете? поскольку у меня есть только объект как параметр, у меня нет доступа к его конкретному полю ID, поэтому я не могу использовать session.get(Object.class(), id);

Ответ 2

Как правило, NHibernate может полагаться на несохраненное значение, чтобы определить, следует ли ему вставлять или создавать объект. Однако, поскольку вы назначаете идентификатор, для NHibernate это похоже на то, что ваша сущность уже сохранена. Поэтому вам нужно полагаться на версию вашего объекта, чтобы NHibernate знал, что это новый объект. См. Следующую ссылку о том, как выполнить модификацию объекта:

http://devlicio.us/blogs/mike_nichols/archive/2008/07/29/when-flushing-goes-bad-assigned-ids-in-nhibernate.aspx

Ответ 3

Использовать метод session.SaveOrUpdate(object).

Ответ 4

Вы можете сделать

Obj j = session.get(Object.class(), id);
if (j != null)
   session.merge(myObj);
else
   session.saveOrUpdate(myObj);

Ответ 5

вызвать hibernate.saveOrUpdate(), который будет проверять, находится ли объект в базе данных, обновить его, если он есть, и сохранить (т.е. вставить), если это не так.