Сеанс NHibernate.Flush() Отправка запросов на обновление, когда обновление не произошло

StackOverflow https://stackoverflow.com/questions/34852

  •  09-06-2019
  •  | 
  •  

Вопрос

У меня сеанс NHibernate.В этом сеансе я выполняю ровно 1 операцию, которая заключается в запуске этого кода для получения списка:

public IList<Customer> GetCustomerByFirstName(string customerFirstName)
{
return _session.CreateCriteria(typeof(Customer))
    .Add(new NHibernate.Expression.EqExpression("FirstName", customerFirstName))
    .List<Customer>();
}

Я звоню Session.Flush() в конце HttpRequest, и я получаю HibernateAdoException.NHibernate передает инструкцию update в базу данных и вызывает нарушение внешнего ключа.Если я не запущу flush, запрос завершается без проблем.Проблема здесь в том, что мне нужна очистка на случай, если есть изменения, которые происходят в других сеансах, поскольку этот код повторно используется в других областях.Есть ли еще один параметр конфигурации, который я, возможно, упускаю?


Вот код из исключения:

[SQL: UPDATE CUSTOMER SET first_name = ?, last_name = ?, strategy_code_1 = ?, strategy_code_2 = ?, strategy_code_3 = ?, dts_import = ?, account_cycle_code = ?, bucket = ?, collector_code = ?, days_delinquent_count = ?, external_status_code = ?, principal_balance_amount = ?, total_min_pay_due = ?, current_balance = ?, amount_delinquent = ?, current_min_pay_due = ?, bucket_1 = ?, bucket_2 = ?, bucket_3 = ?, bucket_4 = ?, bucket_5 = ?, bucket_6 = ?, bucket_7 = ? WHERE customer_account_id = ?]

Никакие параметры не отображаются как переданные.

Это было полезно?

Решение

Я уже видел это однажды, когда одна из моих моделей не была правильно отображена (неправильно использовались обнуляемые типы). Можете ли вы вставить свою модель и карту?

Другие советы

Всегда будьте осторожны с обнуляемыми полями, когда имеете дело с NHibernate.Если ваше поле в базе данных имеет значение NULL, убедитесь, что оно соответствует .Класс NET также использует тип Nullable.В противном случае будут происходить всевозможные странные вещи.Симптомом обычно является то, что NHibernate попытается обновить запись в базе данных, даже если вы не изменили никаких полей с тех пор, как прочитали объект из базы данных.

Следующая последовательность объясняет, почему это происходит:

  1. NHibernate извлекает необработанные данные объекта из базы данных, используя ADO.NET
  2. NHibernate создает объект и задает его свойства
  3. Если поле базы данных содержит значение NULL, то свойству будет присвоено значение по умолчанию для его типа:
    • свойствам ссылочных типов будет присвоено значение null
    • свойствам целых чисел и типов с плавающей запятой будет присвоено значение 0
    • свойствам логического типа будет присвоено значение false
    • свойствам типа DateTime будет присвоено значение DateTime.MinValue
    • и т.д.
  4. Теперь, когда транзакция зафиксирована, NHibernate сравнивает значение свойства с исходным значением поля, которое оно считало из базы данных, и поскольку поле содержало NULL, но свойство содержит ненулевое значение, NHibernate считает свойство загрязненным и принудительно обновляет enity.

Это не только снижает производительность (вы получаете дополнительный доступ к базе данных и дополнительное обновление каждый раз, когда извлекаете объект), но также может привести к трудноразрешимым ошибкам со столбцами DateTime.Действительно, когда свойство DateTime инициализируется значением по умолчанию, ему присваивается значение 1/1/0001.Когда это значение сохраняется в базе данных, ADO.NET SqlClient не может преобразовать его в допустимое значение SqlDateTime, поскольку наименьшее возможное значение SqlDateTime равно 1/1/1753!!!

Самое простое исправление - заставить свойство класса использовать тип с нулевым значением, в данном случае "DateTime?".В качестве альтернативы, вы могли бы реализовать пользовательский преобразователь типов, реализовав IUserType с его методом Equals, должным образом сравнивая DBNull.Значение с любым значением по умолчанию вашего типа значения.В нашем случае Equals должно было бы возвращать true при сравнении 1/1/0001 с DBNull.Значение.Реализовать полнофункциональный IUserType на самом деле не так уж сложно, но для этого требуется знание NHibernate trivia, поэтому приготовьтесь к некоторому существенному поиску в Google, если вы решите пойти этим путем.

Я также столкнулся с этой проблемой в NH 2.0.1, когда пытался скрыть обратные концы пакетов «многие ко многим», используя access = " noop " (подсказка: это не работает).

Преобразование их в access = " field " + добавление поля в классе решило проблему. Довольно сложно отследить их, хотя.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top