РЕДАКТИРОВАТЬ: Первоначально я опубликовал другой «ответ», который на самом деле не решил проблему, но я хочу задокументировать мои выводы здесь для всех, кто может столкнуться с этим.
После нескольких дней попыток выяснить проблему и решить ее, будучи крайне разочарованным, потому что проблема, казалось, ушла на некоторое время, а затем периодически возвращалась (заставляя меня много раз думать, что внесенное мной исправление исправило ее) , когда на самом деле это не так), я считаю, что я разыскал реальную проблему.
Несколько раз после того, как я переключил уровень log4net для NHibernate на DEBUG, проблема исчезла, но я наконец смог получить ошибку с этим уровнем журнала. В журнал включены следующие строки:
Building an IDbCommand object for the SqlString: SELECT LAST_INSERT_ID()
...
NHibernate.Type.Int32Type: 15:10:36 [8] DEBUG NHibernate.Type.Int32Type: returning '0' as column: LAST_INSERT_ID()
NHibernate.Id.IdentifierGeneratorFactory: 15:10:36 [8] DEBUG NHibernate.Id.IdentifierGeneratorFactory:
Natively generated identity: 0
И, глядя вверх, я увидел несколько строк:
NHibernate.AdoNet.ConnectionManager: 15:10:36 [8] DEBUG NHibernate.AdoNet.ConnectionManager: aggressively releasing database connection
NHibernate.Connection.ConnectionProvider: 15:10:36 [8] DEBUG NHibernate.Connection.ConnectionProvider: Closing connection
Кажется, что во время очистки сеанса и выполнения INSERT NHibernate закрывал соединение между оператором INSERT и "SELECT LAST_INSERT_ID ()", чтобы получить идентификатор, сгенерированный MySQL для оператора INSERT. Или, скорее, я должен сказать, что иногда закрывал соединение, что является одной из причин, по которой я считаю, что проблема была прерывистой. Я не могу найти ссылку сейчас, но я полагаю, что я также прочитал во всех моих поисках, что MySQL иногда возвращает правильное значение из LAST_INSERT_ID (), даже если соединение закрыто и повторно открыто, что является еще одной причиной Я считаю, что это было с перебоями. Однако в большинстве случаев LAST_INSERT_ID () вернет 0, если соединение закрыто и вновь открыто после INSERT.
Похоже, есть 2 способа исправить эту проблему. Во-первых, это патч , доступный здесь , который выглядит так, как будто он войдет в NHibernate 2.1.1, или который вы можете использовать для создания своей собственной сборки NHibernate, что заставляет INSERT и SELECT LAST_INSERT_ID () работать вместе , Во-вторых, вы можете установить для connection.release_mode значение on_close, как описано в этом сообщении в блоге , которое запрещает NHibernate закрывать соединение до тех пор, пока ISession не будет явно закрыт.
Я выбрал последний подход, который делается в FluentNHibernate следующим образом:
Fluently.Configure()
...
.ExposeConfiguration(c => c.Properties.Add("connection.release_mode", "on_close"))
...
У этого также был побочный эффект резкого ускорения моего кода. То, что потребовалось 20-30 секунд для запуска (когда это только сработало до того, как я внес это изменение), теперь выполняется через 7-10 секунд, поэтому выполняет ту же самую работу в ~ 1/3 времени.