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

NHibernate Session.Flush() Отправка запросов обновления при отсутствии обновления

У меня есть сеанс 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, и я получаю a HibernateAdoException. NHibernate передает сообщение об обновлении в db и вызывает нарушение внешнего ключа. Если я не запускаю 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 = ?]

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

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

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

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

Ответ 3

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

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