У меня есть приложение ASP.NET MVC 3, использующее NHibernate над базой данных PostgreSQL.
На моем веб-сайте есть операция, которая принимает все сущности (я называю их единицами ) и, если они удовлетворяют определенному условию, обновляет одно из своих свойств (столбец).Вся эта операция заключена в транзакцию.
Сегодня я столкнулся с проблемой, когда заметил, что иногда (точно) одна единица не обновляется во время операции, даже если она должна (он удовлетворяет требуемому условию).
Теперь я обнаружил, что это потому, что в то же время на сервер поступает много других запросов, которые также имеют дело с единиц (для этого запроса это всегда один блок , который проверяется и, если необходимо, модифицируется).
Итак, в одном потоке у меня работает следующий код:
ISession session = sessionBuilder.GetSession();
using (ITransaction transaction = session.BeginTransaction())
{
var unitsToBeUpdated = session.QueryOver<Unit>()
.Where(x => x.Status == STATUS_TRANSLATED)
.JoinQueryOver<UnitParent>(u => u.Parent)
.JoinQueryOver<Document>(p => p.Document)
.Where(d => d.Job == job);
foreach (Unit unit in unitsToBeUpdated.List<Unit>())
{
unit.Status = STATUS_CONFIRMED;
session.SaveOrUpdate(unit);
}
transaction.Commit();
}
и во втором потоке я запускаю этот код (несколько раз, каждый раз для разных unitId
)
Unit unit;
using (ITransaction transaction = sessionBuilder.GetSession().BeginTransaction())
{
unit = unitRepository.GetById(unitId);
}
using (ITransaction transaction = sessionBuilder.GetSession().BeginTransaction())
{
unit.LastCategory = statisticsHarvester.AddWords(job, unit);
unitRepository.Update(unit);
transaction.Commit();
}
В этом втором потоке открытие транзакции показано дважды, потому что на самом деле эти две транзакциисоздаются в разных функциях.
Таким образом, запросы идут как
Request A started...
Request B(unitId = 0) started...
Request B(unitId = 0) finished
Request B(unitId = 1) started...
Request B(unitId = 1) finished
....
Request B(unitId = n) started...
Request A finished
Request B(unitId = n) finished
Request B(unitId = n+1) started...
Request B(unitId = n+1) finished
....
Возможно, я не до конца понимаю весь мир транзакций и одновременного доступа, но вв этой ситуации не должно ли быть невозможным для первого потока обновить только некоторые модули?Я ожидал, что вся транзакция откатится, что-то пошло не так.В чем здесь проблема?
Спасибо.
РЕДАКТИРОВАТЬ: наконец-то я решил эту проблему с помощью функции «динамического обновления» в NHibernate - в моем случае два запроса не изменяют одно и то жеполе сущности, поэтому оно жизнеспособно.