Рекомендуемое решение
Я бы посоветовал в запросе отфильтровать текущую запись.
ICriteria crit = CurrentSession.CreateCriteria(typeof (Pharmacy));
crit.Add(Restrictions.Not(Restrictions.Eq("PharmacyId", pharmacyIdToIgnore)));
crit.Add(Restrictions.Eq("ClientName", clientName));
crit.Add(Restrictions.Eq("FriendlyUrl", friendlyUrl));
crit.AddOrder(Order.Asc(PHARMACY_NAME));
crit.SetProjection(Projections.RowCount);
return crit.UniqueResult<int> == 0;
В идеале, вы должны выполнить эту проверку, прежде чем изменять саму сущность. Также см. ответ Руны о размещении ограничения в БД для обеспечения соблюдения этого ограничения. Эта проверка не для того, чтобы предотвратить дубликаты, а для того, чтобы попытаться обнаружить их раньше, чтобы вы могли представить более приятное сообщение об ошибке и не пытаться зафиксировать изменение, которое, как вы знаете, завершится неудачей.
Почему это происходит (FlushMode)
Это сделано для того, чтобы результаты вашего запроса соответствовали изменениям, которые вы внесли локально. Поскольку NHibernate пытается смоделировать ваши сущности так, как будто они всегда доступны в памяти, автоматически сохраняя их в базе данных при необходимости.
Вы можете изменить это, посмотрев на настройку автоматического смыва. Существует значение по умолчанию на фабрике сеансов, используемое для всех вновь создаваемых сеансов, и индивидуальный параметр для каждого сеанса.
Значением по умолчанию является FlushMode.Auto
, которое будет сохраняться при фиксации транзакции или перед выполнением любого запроса, на который могут повлиять изменения в памяти. Если вы измените его на FlushMode.Commit
, то он сохранит изменения в базе данных только при фиксации транзакции или при сохранении нового объекта, который использует стратегию первичного ключа, например, идентификатор.
Вы также можете вручную сохранить изменения текущего сеанса обратно в базу данных в любое время, используя Session.Flush
.