2011-04-13 3 views
3

웹 어플리케이션에서 NHibernate를 사용할 때, 보통 IoC 컨테이너가 요청 당 ISession을 열고 닫고 트랜잭션을 커밋/롤백하도록 돌릴 것입니다. HTTP의 특성상 이러한 응용 프로그램에서 명확한 작업 단위를 쉽게 정의 할 수 있습니다.장기 실행 작업을위한 NHibernate의 트랜잭션과 범위 지정하기

이제는 일정 스케줄러에서 정기적으로 호출하여 뉴스 레터를 보내는 작은 프로그램을 작성하는 작업이 수행되었습니다. 각 Subscriber 객체가 루프 내에 업데이트하는 방법을

var subscribers = _session 
    .QueryOver<Subscription>() 
    .Where(s => !s.HasReceivedNewsletter) 
    .List(); 

foreach (var subscriber in subscribers) 
{ 
    SendNewsletterTo(subscriber); 
    subscriber.HasReceivedNewsletter = true; 
} 

주의 사항 : 뉴스 레터와 가입자 모두의 개념은 이미 잘 우리의 도메인 모델에서 엔티티를 정의하고, 모든 가입자에게 뉴스 레터를 보내는 이와 비슷한 일을 포함하는 것 그녀가 지금 뉴스 레터를 받았다는 녹음. 메일 전송 프로그램이 중단되어야한다면 다시 시작할 수 있으며 중단 한 곳에서 뉴스 레터를 계속 보낼 수 있습니다.

내가 직면 한 문제는 단위 작업 패턴을 정의하고 구현하는 데 있습니다. 루프의 각 반복 끝에 데이터베이스에 변경 사항을 적용해야 할 것입니다. 루프 바디를 using (var trans = _session.BeginTransaction()) 블록으로 간단히 감싸는 것은 실행 시간이 매우 비쌉니다. 또한이 장기 실행 프로세스와 동일한 데이터베이스를 사용하는 다른 (웹) 응용 프로그램간에 잠금 문제가 발생하는 것 같습니다.

NHibernate 트랜잭션에 대한 몇 가지 기사와 문서를 읽은 후에는 잠금 문제를 피하기 위해 세션에서 구독자 목록을 분리하고 각각을 루프 본문의 새로운 세션에 다시 연결해야 할 필요가 있다고 생각하게되었습니다 . 그러나 이것이 성능을 위해 어떻게 작동 할 지 확신하지 못합니다.

그래서 NHibernate 전문가들은 어떻게 이런 장기 실행 작업을 설계하고 구현하겠습니까?

답변

0

트랜잭션이없는 상태없는 세션은 여기에서 더 잘할 것이라고 생각하지 않습니까?

+0

Google에서는 처음 들어 본 적이 없지만 Google의 처음 몇 줄부터 보았을 것입니다. 어떻게 그리고 왜 내 문제를 해결할 것인지에 대해 더 말해주세요 :) –

+0

"무국적 세션"힌트로 인해이 대답을 받아 들일 것입니다. 그러나, 나는 커뮤니티를 위해서 @Sly (또는 다른 누구)가 주제를 조금 더 확장하기를 희망하면서 나의 업보 트를 막고있다. –

+0

상태없는 세션은 HasReceivedNewsletter 플래그에 대한 동적 업데이트를 할 수 없다. , 나중에 전체 구독자 행에 대한 업데이트가 있거나, 아마도 HQL 업데이트를 통해 수동으로 업데이트해야합니다. 상태없는 세션은 전혀 세션과 같지 않으며 NHibernate를 사용하여 데이터베이스 행을 Hibernate 객체로 변환합니다. –

1

여기서 비동기식 내구성 메시지를 사용하고 싶지 않으십니까? NServiceBus, Rhino Service Bus 또는 MassTransit과 같은 것입니다. 최대한 많은 메시지를 보낼 필요가없는 것 같아서 사용자 당 1 개의 영구 메시지로 비동기 적으로 처리해야한다고 생각합니다.

0

세션에 여러 트랜잭션을 수행하는 데 문제가 없습니다. 독립적 인 작업이므로 단일 구독자를 업데이트하는 트랜잭션 범위를 지정하는 것이 좋습니다. 구독자 수와 실패 가능성에 따라 한 번에 소수의 구독자를 확보하는 것이 가장 좋습니다.

+0

당신은 이것을위한 명시 적 트랜잭션이 필요 없을 것입니다 -이 루프는 원자 적 단일 업데이트 명령을 생성합니다. –

관련 문제