Почему NHibernate не отражает состояние в памяти, когда обновления производятся с помощью хранимой процедуры? - PullRequest
2 голосов
/ 30 января 2020

У меня есть процесс, при котором у меня есть сеанс NHibernate, который я использую для выполнения запроса к базе данных. Затем я перебираю коллекцию результатов, и для каждой итерации, используя один и тот же сеанс NHibernate, я вызываю SQL хранимую процедуру (используя CreateSQLQuery() & ExecuteUpdate()), которая в итоге выполняет обновление поля для этого entity.

Когда он завершит итерацию по списку (и вызовет SP x раз), если я проверю базу данных непосредственно в SSMS, я вижу, что применяется ОБНОВЛЕНИЕ для каждой строки.

Однако в моем коде, если я затем сразу же выполню тот же начальный запрос снова, чтобы получить этот список сущностей, он не будет отражать обновления, которые SP сделал для каждой строки - значение по-прежнему равно NULL.

В моем приложении не указано поведение кэша в сравнении с конфигурацией NHibernate, и я экспериментировал с различными SetCacheMode() при вызове запроса, но, похоже, ничто не имеет значения - значения, которые я вижу непосредственно в база данных была обновлена, не возвращаются как обновленные, когда я повторно запрашиваю (используя Session.QueryOver()) базу данных (используя тот же сеанс).

1 Ответ

2 голосов
/ 30 января 2020

Вызывая CreateSQLQuery (для обновления базы данных, отдельная строка или несколько строк не имеет значения), фактически вы выполняете операцию в стиле DML , которая не обновляет состояние в памяти.
Любой звонок на CreateSQLQuery или CreateQuery не будет использовать / отражать отслеживание. Они считаются выходящими за рамки единицы работы.
Эти операции напрямую влияют на базовую базу данных, игнорируя любое состояние в памяти.

14.3. Операции в стиле DML
Как уже говорилось, автоматизация c и прозрачное отображение объекта / реляции связаны с управлением состоянием объекта. Это означает, что состояние объекта доступно в памяти, , следовательно, манипулирование (используя операторы SQL Data Manipulation Language (DML): INSERT, UPDATE, DELETE) данными непосредственно в базе данных не повлияет на состояние в памяти . Тем не менее, NHibernate предоставляет методы для массового выполнения DML-операторов в стиле SQL, которые выполняются с помощью языка запросов Hibernate (HQL). Также доступна реализация Linq.

Они (могут) работать с объемными данными. Они необходимы в некоторых сценариях ios для повышения производительности. С этим отслеживание не работает; так что да, состояние в памяти становится недействительным. Вы должны использовать их осторожно.

Если я затем сразу же выполню тот же первоначальный запрос, чтобы получить этот список сущностей, он не будет отражать обновления, которые SP сделал для каждой строки - значение по-прежнему NULL.

Это связано с кэшем первого (сеансового) уровня. Это всегда включено по умолчанию и не может быть отключено с помощью ISession.

Когда вы сначала загружаете объекты, это попадание в базу данных. Вы получаете объекты из базы данных - l oop через них - выполняете команды, находящиеся вне единицы работы (как описано выше) - и снова выполняете тот же запрос дважды для загрузки одинаковых объектов в одном экземпляре ISession. Второй вызов вообще не попадает в базу данных .

Он просто возвращает экземпляры из памяти. Поскольку ваши экземпляры в памяти вообще не обновляются, вы всегда получаете оригинальные экземпляры.

Чтобы получить обновленные экземпляры, закройте первый сеанс и перезагрузите экземпляры с новым сеансом.

Для получения дополнительной информации подробнее см. Как работает Hibernate Query Cache

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...