2016-03-23 2 views
0

Когда мы выпустили последнюю пятницу, я получил сообщение об ошибке, которое я не получаю при принятии. Сообщение об ошибке:NHibernate IStatelessSession Ошибка CreateQuery

could not execute update query[SQL: delete from dbo.MyTable where col1=? and col2=? and col3=? and col4=? and col5=?]

Мой C# код выглядит следующим образом:

var hqlDelete = "DELETE MyTable m WHERE m.Col1 = :var_1 AND m.Col2 = :var_2 AND m.Col3= :var_3 AND m.Col4 = :var_4 AND m.Col5= :var_5"; 
var deletedEntities = session.CreateQuery(hqlDelete) 
          .SetString("var_1", variable1) 
          .SetString("var_2", variable2) 
          .SetString("var_3", variable3) 
          .SetString("var_4", variable4) 
          .SetString("var_5", variable5) 
          .ExecuteUpdate(); 
transaction.Commit(); 
session.Close(); 

Теперь, как я сказал, ошибка не срабатывает, когда тестирование на прием. Кроме того, когда я тестирую базу данных производства (код с моего сайта разработчика), она работает без проблем.

Код запускается при вызове веб-службы и POST «измерение». Единственное различие заключается в том, что я звоню в службу при тестировании, а на производстве другая компания отправляет измерения в веб-службу.

Я думаю, что это может иметь какое-то отношение к количеству сеансов/транзакций, но на самом деле это не объясняет, почему переменные отображаются в сообщении об ошибке как ?.

Любые идеи? Есть ли больше информации, которую я мог бы предоставить, чтобы вы могли помочь мне с этим?

Edit: InnerExeption является

{"Transaction (Process ID 68) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction."}

+2

Во-первых, показать полный стек исключений .. эта часть выше будет только началом ... реальная и интересная информация будет следовать ... –

+1

Как указано Radim, ваше сообщение об ошибке недостаточно. Он просто говорит, чего он не может сделать. Обычно это дает некоторые причины. Сведения о журнале исключения, включая его 'InnerException'. Если у вас их больше нет, добавьте log4net, настройте его для регистрации как минимум предупреждений и выше, и NHibernate затем опубликует подробные журналы об ошибке. –

+0

Хорошо спасибо. Я надеялся, что это была какая-то типичная ошибка или что-то в этом роде. Это отчасти трудно отлаживать, так как я должен следовать плану выпуска (я могу выпустить раз в месяц) и, следовательно, только тест на прием. Поэтому, даже если я добавлю log4net, мне придется подождать месяц, прежде чем я смогу понять, что такое ошибки. – Tjab

ответ

1

Решение тупики может быть трудно дело, особенно при использовании ОРМ. Тупики обычно возникают из-за того, что блокировки объектов базы данных не получаются в одном порядке разными процессами (или потоками), заставляя их ждать друг друга.

ORM не дает вам большого контроля над заказом на блокировку. Вы можете переделать свои запросы, но это может быть утомительным. Особенно, когда кеширование приводит к тому, что некоторые из них не попадают в БД. Более того, это нужно делать с тем же заказом на любом другом приложении, используя одну и ту же базу данных.

Вы можете обнаружить ошибки в тупике и выполнить то, что говорится в сообщении: повторите весь процесс. С NHibernate это означает отказ от текущего сеанса и повторение всей вашей работы.

Если в вашей базе данных есть SQL Server, есть значение по умолчанию, которое значительно увеличивает риск блокировки: отключает read committed snapshot mode. Если он отключен в вашей базе данных, вы можете значительно снизить риски взаимоблокировки, включив его. Этот режим позволяет читать считываемые уровни изоляции, чтобы прекратить выпуск блокировок чтения.

Вы можете проверить эту настройку с

select snapshot_isolation_state_desc, is_read_committed_snapshot_on 
    from sys.databases 
    where name = 'YourDbName' 

Вы можете включить этот параметр с

alter database YourDbName 
    set allow_snapshot_isolation on 

alter database YourDbName 
    set read_committed_snapshot on 

Это требует наличия NONE запуска транзакции на целевом дб. И, конечно, для этого требуются права администратора на БД.

В приложении, для которого у меня не было возможности изменить этот параметр, мне пришлось пойти более причудливым способом: установить режим изоляции по умолчанию NHibernate (connection.isolation configuration parameter) на ReadUncommitted. Мое приложение было главным образом доступно только для чтения, и я явно использовал режим изоляции для нескольких транзакций, которые нужно было читать, а затем записывать данные (например, с помощью session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted)).

Вы также должны проверить режимы изоляции, которые в настоящее время используются всеми приложениями с использованием базы данных: некоторые из них используют более высокий уровень изоляции, чем требуется на самом деле? (RepeatableRead и Serializable следует избегать, если это возможно.) Это трудоемкий процесс, поскольку он требует хорошего понимания уровней изоляции при изучении каждого варианта использования для определения того, что является соответствующим минимальным уровнем изоляции.

+0

Спасибо за очень сложный ответ! Обозначение моментального снимка/считывание действительно установлено в false/0, и я не знал об этом параметре. – Tjab

+1

Я забыл пункт о режиме чтения снятого снимка: он больше использует пространство tempdb. Ваш администратор базы данных должен знать об этом. –

+0

Хм, мне тоже нужно посмотреть на это. Сама база данных довольно велика, говоря о почти 400 миллионах записей в 1 таблице на данный момент ... не знаю, «чем больше таблица/db, тем больше используется пространство tempdb», но если это так. :) – Tjab

Смежные вопросы