문제

MySQL 데이터베이스가 장착 된 ASP.NET MVC 앱에서 nhibernate/fluent nhibernate를 사용하고 있습니다. 나는 상당히 많은 데이터를 읽고 (삽입 된 금액), 처리하고, 약 50 개의 레코드를 삽입하는 작업을 수행하는 작업을 수행하고 있습니다. 요청 당 하나의 issession이 있습니다. 시작/종료 요청 이벤트 처리기에서 생성/파괴됩니다 (정확히 좋아요 http://ayende.com/blog/archive/2009/08/06/challenge-find-thebug-fixes.aspx), 그리고 나는 데이터를 읽고 새로운 개체를 추가하고 있습니다 (섹션 16.3에서와 같이 https://www.hibernate.org/hib_docs/nhibernate/html/example-parentchild.html), 그리고 마지막으로 세션에서 flush ()를 호출하여 실제로 모든 인서트를 실행합니다.

데이터를 꺼내고 게으른로드가 잘 작동하며, 플러시를 호출 할 때 정확히 2 개의 새로운 레코드가 삽입되고 있습니다 (테이블을 수동으로 확인하고 있습니다). 그런 다음 다음 오류가 발생합니다.

NonUiqueObjectException : 동일한 식별자 값을 가진 다른 객체는 이미 세션과 관련되어 있습니다 : 0, 엔티티 : ...

나는 nhibernate를 처음 접했고 솔루션을 검색하는 동안 ID 속성 생성기를 기본 및 ID로 명시 적으로 설정하려고 시도했습니다 (MySQL 데이터베이스이고 ID 열은 auto_increment가있는 int). 그러나 ID 속성은 0입니다. 그러나 여전히 오류가 발생합니다.

나는 또한 다른 시간에 플러시를 호출하려고 시도한 다음 (효과적으로 삽입 된 인서트) 동일한 오류를 얻지 만 0 이외의 ID 값과 프로세스에서 겉보기에 임의의 지점에서는 시나리오이지만 때로는 다른 시점에서 수행합니다).

여기서 어디로 가야할지 잘 모르겠습니다. 모든 도움이나 통찰력은 대단히 감사하겠습니다.

편집 : 아래 답변을 참조하십시오.

도움이 되었습니까?

해결책

편집 : 원래 문제를 해결하지 못한 다른 "답변"을 게시했지만, 그 결과를 발견 할 수있는 다른 사람을 위해 여기에 내 결과를 문서화하고 싶습니다.

며칠이 지난 후 문제를 파악 하고이 문제를 해결하려고 노력한 후, 문제가 잠시 동안 사라지고 간헐적으로 돌아 오는 것처럼 보였기 때문에 극도로 좌절했습니다. 사실은 그렇지 않았습니다), 나는 실제 문제를 추적했다고 생각합니다.

NHibernate의 Log4Net 레벨을 디버그로 돌린 후 몇 번이나 문제가 사라졌지 만 마침내 해당 로그 레벨로 오류를 얻을 수있었습니다. 로그에는이 선이 포함되어 있습니다.

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

세션을 플러시하고 인서트를 수행하는 동안 Nhibernate는 삽입 문과 "select atrensert_id ()"사이의 연결을 닫으려면 삽입 문에 대해 MySQL이 생성 한 ID를 얻었습니다. 또는 오히려, 나는 그것이 그렇게 말해야합니다 때때로 연결을 닫는 것은 문제가 간헐적이라고 생각하는 이유 중 하나입니다. 지금은 링크를 찾을 수 없지만 MySQL이 모든 검색에서 읽었습니다. 때때로 연결이 닫히고 재개 되더라도 Last_insert_id ()에서 올바른 값을 반환합니다. 이것이 간헐적이라고 생각하는 또 다른 이유입니다. 그러나 대부분의 경우, 삽입 후 연결이 닫히고 다시 열면 Last_insert_id ()가 0을 반환합니다.

이 문제를 해결하는 방법에는 두 가지가있는 것으로 보입니다. 첫 번째는 패치입니다 여기에서 사용할 수 있습니다 그것은 nhibernate 2.1.1로 만들거나, 삽입물을 강제하고 last_insert_id ()가 함께 실행되도록 선택할 수있는 nhibernate를 만들기 위해 사용할 수있는 것처럼 보입니다. 둘째, connection.release_mode를 on_close로 설정할 수 있습니다. 이 블로그 게시물 이는 nhibernate가 명시 적으로 닫힐 때까지 연결을 닫지 못하게합니다.

후자의 접근 방식을 취했습니다.

Fluently.Configure()
    ...
    .ExposeConfiguration(c => c.Properties.Add("connection.release_mode", "on_close"))
    ...

이것은 또한 내 코드 속도를 크게 높이는 부작용이있었습니다. 실행하는 데 20-30 초가 걸렸던 것 (이 변경을하기 전에 일을했을 때)은 이제 7-10 초 안에 실행되고 있으므로 시간에 ~ 1/3에서 동일한 작업을 수행하고 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top