Как можно удалить объект в nhibernate, имея только его идентификатор и тип?
-
19-09-2019 - |
Вопрос
Мне интересно, как можно удалить объект, имеющий только его идентификатор и тип (как в mapping), используя NHibernate 2.1?
Решение
Если вы используете отложенную загрузку, Load создает только прокси.
session.Delete(session.Load(type, id));
С NH 2.1 вы можете использовать HQL.Не уверен, как это выглядит на самом деле, но что-то вроде этого: обратите внимание, что это зависит от SQL-инъекции - если возможно, используйте параметризованные запросы вместо setParameter()
session.Delete(string.Format("from {0} where id = {1}", type, id));
Редактировать:
Для загрузки вам не нужно знать имя столбца Id.
Если вам нужно это знать, вы можете получить это с помощью метаданных NH:
sessionFactory.GetClassMetadata(type).IdentifierPropertyName
Еще одна правка.
session.Delete()
создает экземпляр объекта
При использовании session.Delete(), NH в любом случае загружает объект.Поначалу мне это не нравилось.Тогда я осознал свои преимущества.Если объект является частью сложной структуры, использующей наследование, коллекции или "любые" ссылки, это на самом деле более эффективно.
Например, если класс A
и B
оба наследуются от Base
, он не пытается удалить данные в таблице B
когда фактический объект имеет тип A
.Это было бы невозможно без загрузки самого объекта.Это особенно важно, когда существует много унаследованных типов, каждый из которых также состоит из множества дополнительных таблиц.
Такая же ситуация возникает, когда у вас есть коллекция Base
s, которые, оказывается, являются всеми экземплярами A
.При загрузке коллекции в память NH знает, что ей не нужно удалять какие-либо B
-всякая всячина.
Если сущность A
имеет коллекцию B
s, который содержит C
s (и так далее), он не пытается удалить какие-Либо C
ы, когда сбор B
s пусто.Это возможно только при чтении сборника.Это особенно важно, когда C сам по себе сложный, объединяющий еще больше таблиц и так далее.
Чем сложнее и динамичнее структура, тем эффективнее она загружает фактические данные вместо "слепого" их удаления.
При удалении HQL есть подводные камни
HQL удаляет, чтобы не загружать данные в память.Но HQL-удаления не настолько умны.Они в основном преобразуют имя объекта в соответствующее имя таблицы и удаляют его из базы данных.Кроме того, он удаляет некоторые агрегированные данные коллекции.
В простых структурах это может работать хорошо и эффективно.В сложных структурах удаляется не все, что приводит к нарушению ограничений или "утечке памяти базы данных".
Заключение
Я также попытался оптимизировать удаление с помощью NH.В большинстве случаев я сдавался, потому что NH все еще умнее, он "просто работает" и обычно достаточно быстр.Один из самых сложных алгоритмов удаления, который я написал, - это анализ определений отображения NH и построение на их основе инструкций delete.И - неудивительно - это невозможно без чтения данных из базы данных перед удалением.(Я просто сократил его, чтобы загружать только первичные ключи.)