Замок ActiveProject извлекает устаревшие данные из FindAllByProperty - PullRequest
0 голосов
/ 09 ноября 2018

У меня есть старое приложение WinForms 4.x, которое использует Castle.ActiveRecord 3.0.0 RC (который, я думаю, является последней доступной версией) поверх NHibernate 3.1.0.4000 (который не является последним, но он был актуален вв то время).

Я заметил странное поведение несоответствия данных внутри одной формы.Он создает TransactionScope для срока жизни формы и не фиксирует его до конца.Он выбирает список объектов и предоставляет для них некоторый пользовательский интерфейс редактирования.Одним из них является флажок для логического свойства IsPrimary.

Предполагается, что только один объект имеет IsPrimary == true, поэтому при установке флажка он имеет значение:

var others = MyData.FindAllByProperty("IsPrimary", true)
        .Where(x => x.Name != current.Name).ToList();
foreach (var data in others)
{
    data.IsPrimary = false;
    data.Save();
}
current.IsPrimary = true;
current.Save();

(что, вероятно, можно было бы сделать более эффективно, но пока игнорируйте это. current - это объект, у которого установлен флажок. И все они имеют уникальные имена.)

Это работает корректно в большинстве случаев.время, но если вы откроете окно, поставьте галочку на каком-то другом элементе (чтобы он делал выше и правильно установил предыдущий на false), а затем, не закрывая окно, попытаетесь снова поставить галочку на первом элементе, вы завершаетес двумя установленными объектами IsPrimary.

Проблема заключается в том, что FindAllByProperty возвращает исходное состояние объекта вне транзакции формы, игнорируя любые изменения.

Если я заменювызов с этим кодом:

var others = MyData.FindAll().Where(x => x.IsPrimary)
        .Where(x => x.Name != current.Name).ToList();

Затем он возвращает правильный результат (включая изменения, внесенные в транзакции формы).

Это известная ошибка?Есть ли обходной путь, отличный от использования FindAll()?


Редактировать : FWIW, использование явных критериев дает тот же результат (он возвращает устаревшие данные, а не правильные данные):

var criteria = DetachedCriteria.For(typeof(MyData))
    .SetResultTransformer(CriteriaSpecification.DistinctRootEntity)
    .Add(Restrictions.Eq("IsPrimary", true))
    .Add(Restrictions.Not(Restrictions.IdEq(current.Id)));
var others = MyData.FindAll(criteria);
// still stale

1 Ответ

0 голосов
/ 10 ноября 2018

здесь играют три вещи вместе:

  • без фиксации данных не изменяется внутри базы данных.
  • когда это возможно, nhibernate преобразует ограничения в SQL, и сервер базы данных выполняет проверки. ТОЛЬКО если возможно.
  • сеанс имеет последовательность, и если возвращается ключ записи (первичный), который уже находится в последовательности, он игнорирует запись (значения) и просто повторно использует объект из кэша.

Это означает, что Restrictions.Eq ("IsPrimary", true) или Where (x => x.IsPrimary) будут (я думаю) работать на сервере базы данных и никогда не смогут увидеть какие-либо данные, только измененные в приложении (иначе). без коммита, ака. временные данные, ака. грязные данные / объекты). Это означает, что ваш список объектов, который вы установили IsPrimary = false, является списком, если более одного объекта в вашем приложении / сеансе / chace имеет IsPrimary = true, но в базе данных все еще IsPrimary = false!

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

  • загружать все объекты без ограничений
  • или сканировать через сессию вручную, чтобы найти все временные / грязные объекты
  • или коммит после каждого изменения IsPrimary

Если возможно, я бы предложил вам переключиться с логического поля в таблице / классе на поле ссылки типа вашего объекта данных в другой таблице / классе только с одной записью и сохранить первичный объект в этом другой стол / класс. Он автоматически разрешит только один первичный оператор AND и вызовет параллелизм, если два сеанса / пользователя попытаются создать первичный одновременно (лучше, чем два примариса: D).

Возможно, ваша структура данных уже имеет своего рода класс Отца / помощника по отношению к вашему классу данных, и что нужно знать Основы ИТ.

Поздравления Juy Juka

...