NHibernate ISession Flush : 언제 어디서 사용해야하며 왜 그런가?


187

나를 완전히 혼란스럽게 만드는 것 중 하나는 , 및 session.Flush을 함께 사용하는 것입니다 .session.Commitsession.Close

때로는 session.Close작동합니다. 예를 들어 필요한 모든 변경 사항을 커밋합니다. 트랜잭션이있을 때 커밋을 사용해야하거나 오류가 발생하면 롤백하도록 선택할 수 있도록 여러 개의 작성 / 업데이트 / 삭제 작업 단위가 필요하다는 것을 알고 있습니다.

그러나 때때로 나는 그 뒤에있는 논리에 의해 정말로 당황하게됩니다 session.Flush. session.SaveOrUpdate()플러시 가 뒤 따르는 예제를 보았지만 플러시를 제거하면 어쨌든 잘 작동합니다. 때로는 세션이 시간 초과되었다고 말하는 Flush 문에 오류가 발생하여 제거하면 해당 오류가 발생하지 않습니다.

플러시를 언제 어디서 사용하는지에 대한 좋은 지침이 있습니까? 이것에 대한 NHibernate 문서를 확인했지만 여전히 간단한 답변을 찾을 수 없습니다.

답변:


236

간단히:

  1. 항상 거래를 사용하십시오
  2. 사용하지 말고 Close(), 대신 명세서 ISession내부로 전화를 감싸 using거나 다른 곳에서 ISession의 수명주기를 관리하십시오 .

에서 문서 :

때때로 ISessionADO.NET 연결 상태를 메모리에 보유 된 객체의 상태와 동기화하는 데 필요한 SQL 문을 실행합니다. 이 프로세스 플러시는 기본적으로 다음 지점에서 발생합니다.

  • Find()또는 일부 호출에서Enumerable()
  • ...에서 NHibernate.ITransaction.Commit()
  • ...에서 ISession.Flush()

SQL 문은 다음 순서로 발행됩니다.

  1. 모든 개체 삽입 (해당 개체를 사용하여 해당 개체를 저장 한 순서와 동일) ISession.Save()
  2. 모든 엔티티 업데이트
  3. 모든 컬렉션 삭제
  4. 모든 컬렉션 요소 삭제, 업데이트 및 삽입
  5. 모든 컬렉션 삽입
  6. 모든 개체 삭제 (해당 개체를 사용하여 해당 개체를 삭제 한 순서와 동일) ISession.Delete()

(단, 고유 ID 생성을 사용하는 객체는 저장할 때 삽입됩니다.)

명시적인 경우를 제외하고 Flush(), 세션이 ADO.NET 호출을 언제 실행하는지에 대한 보장은 없으며, 실행 순서 만 보장 합니다. 그러나 NHibernate는 ISession.Find(..)메소드가 오래된 데이터를 리턴하지 않을 것이라고 보장한다 . 또한 잘못된 데이터를 반환하지도 않습니다.

플러시가 덜 자주 발생하도록 기본 동작을 변경할 수 있습니다. 이 FlushMode클래스는 커밋시에만 플러시 (및 NHibernate ITransactionAPI가 사용되는 경우에만 ), 설명 된 루틴을 사용하여 자동으로 플러시 또는 Flush()명시 적으로 호출 되지 않는 한 플러시하지 않는 세 가지 모드를 정의합니다 . 마지막 모드는 장시간 실행중인 작업 단위에 유용합니다 ISession.

...

이 섹션 도 참조하십시오 .

세션을 종료하는 데는 4 가지 단계가 있습니다.

  • 세션을 플러시
  • 거래를 저 지르다
  • 세션을 닫다
  • 예외 처리

세션 플러시

ITransactionAPI를 사용하는 경우이 단계에 대해 걱정할 필요가 없습니다. 트랜잭션이 커밋되면 암시 적으로 수행됩니다. 그렇지 않으면 ISession.Flush()모든 변경 사항이 데이터베이스와 동기화되도록 호출해야 합니다.

데이터베이스 트랜잭션 커밋

NHibernate ITransaction API를 사용하는 경우 다음과 같습니다.

tx.Commit(); // flush the session and commit the transaction

ADO.NET 트랜잭션을 직접 관리하는 경우 ADO.NET 트랜잭션을 수동으로 Commit()수행 해야 합니다.

sess.Flush();
currentTransaction.Commit();

변경 사항을 커밋하지 않기로 결정한 경우 :

tx.Rollback();  // rollback the transaction

또는:

currentTransaction.Rollback();

트랜잭션을 롤백하면 NHibernate의 내부 상태가 일관성을 유지하도록 현재 세션을 즉시 닫고 버려야합니다.

문제 종결

ISession.Close()세션 종료 를 표시하기 위한 호출 . Close ()의 주요 의미는 세션에 의해 ADO.NET 연결이 포기된다는 것입니다.

tx.Commit();
sess.Close();

sess.Flush();
currentTransaction.Commit();
sess.Close();

고유 한 연결을 제공 한 경우 Close()참조를 리턴하므로 수동으로 닫거나 풀로 리턴 할 수 있습니다. 그렇지 않으면 Close()풀로 반환합니다.


2
저에게는이 라인이 핵심이었습니다. "Close ()의 주된 의미는 세션에 의해 ADO.NET 연결이 포기된다는 것입니다." ISession.Close ()를 호출하지 않으면 DB 시간이 초과 될 때까지 연결이 채워집니다. : o
dave thieben

우리는 일반적으로 세션 세션을 엽니 다 .BeginTransaction () 작업 ... session.Transaction.Commit () 세션 .BeginTransaction () 작업 ... session.Transaction.Commit () 세션 .BeginTransaction () 작업 .. session.Transaction.Commit () 세션을 폐기하십시오.
Agile Jedi

화려한 쓰기와 +1 등-그러나 "닫기를 사용하지 마십시오"라고 말한 후 나중에 "트랜잭션을 롤백하면 현재 세션을 닫고 버려야합니다"
SpaceBison

SQL 문의 순서를 변경할 수 있습니까? 해당 테이블에 제약 조건이 있기 때문에 엔터티 개체와 삽입보다 업데이트를 수행해야 함을 의미합니다.
bob_saginowski

14

NHibernate 2.0부터는 DB 작업을위한 트랜잭션이 필요하다. 따라서 ITransaction.Commit()통화는 필요한 플러시를 처리합니다. 어떤 이유로 NHibernate 트랜잭션을 사용하지 않으면 세션이 자동 플러시되지 않습니다.


1

때때로 ISession은 ADO.NET 연결 상태를 메모리에 보유 된 객체의 상태와 동기화하는 데 필요한 SQL 문을 실행합니다.

항상 사용

 using (var transaction = session.BeginTransaction())
 {
     transaction.Commit();
 }

데이터베이스에 저장하기 위해 변경 사항이이 변경 사항보다 커밋 된 후 transaction.Commit ();


0

다음은 session.Flush ()없이 실패하는 코드의 두 가지 예입니다.

http://www.lucidcoding.blogspot.co.uk/2012/05/changing-type-of-entity-persistence.html

마지막에, ID 삽입을 설정하고 엔티티를 저장 한 다음 플러시 한 다음 ID 삽입을 해제하는 코드 섹션을 볼 수 있습니다. 이 플러시가 없으면 ID 삽입을 켜고 끈 다음 엔티티를 저장하는 것처럼 보였습니다.

Flush ()를 사용하면 무슨 일이 있었는지 더 잘 제어 할 수있었습니다.

또 다른 예는 다음과 같습니다.

TransactionScope 내에서 NServiceBus 메시지 보내기

나는 이것에 대한 이유를 완전히 이해하지 못하지만 Flush ()는 내 오류가 발생하지 않도록했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.