2010-04-23 5 views
1

SOAP 웹 서비스 집합에서 사용자는 사용자 지정 SOAP 헤더 (사용자 이름/암호)로 인증됩니다. 때마다 사용자가 다음과 같은 인증 방법을 인증하고 NHibernate에 세션에서 사용자 개체를 검색하기 위해 호출되는 WS 전화 :C#의 SOAP 및 NHibernate 세션

는 WS 작업 세션이 잘 정리되고 모든 작품 이루어집니다
[...] 
public Services : Base { 
    private User user; 

    [...] 
    public string myWS(string username, string password) 
    { 
     if(Auth(username, password)) { [...] } 
    } 
} 

public Base : WebService { 

    protected static ISessionFactory sesFactory; 
    protected static ISession session; 

    static Base { 
    Configuration conf = new Configuration(); 
      [...] 
    sesFactory = conf.BuildSessionFactory(); 
    } 

    private bool Auth(...) {  

     session = sesFactory.OpenSession(); 

     MembershipUser user = null; 
      if (UserCredentials != null && Membership.ValidateUser(username, password)) 
      { 
      luser = Membership.GetUser(username); 
      } 
     ... 
     try { 
     user = (User)session.Get(typeof(User), luser.ProviderUserKey.ToString()); 
} catch { 
     user = null; 
      throw new [...] 
     } 

     return user != null; 
    } 

} 

: WSS에 생성, 수정 및 개체 변경 Nhibernate DB에 저장하십시오.

사용자 (동일한 사용자 이름/암호)가 다른 클라이언트 (기계)에서 동시에 동일한 WS를 호출 할 때 문제가 발생합니다. 저장된 개체의 상태가 일치하지 않습니다.

세션을 올바르게 관리하려면 어떻게해야합니까? 검색 한 및 NHibernate에서 세션 관리에 대한 설명서는 정말 광대합니다. 사용자 객체를 잠글까요? 동일한 사용자의 WS 호출간에 "세션 공유"관리를 설정해야합니까? 트랜잭션을 정통한 방법으로 사용해야합니까?

감사

갱신 1은

예, mSession는 '세션'입니다. 심지어 비 정적 세션으로 갱신 2

는 DB에 저장된 데이터가 일치하지 않는 객체.

try { 
    Auth([...]); 
} catch { 
    // .... 
} 
var return_value = [...]; 
try { 
    using(ITransaction tx = session.Transaction) 
    { 
    tx.Begin(); 

    MyType obj = new MyType(); 
    user.field = user.field - obj.field; // The fields names are i.e. but this is actually what happens. 

    session.Save(user); 
    session.Save(obj); 

    tx.Commit(); 

    return_value = obj.another_field; 
    } 
} catch ([...]) { 
    // Handling exceptions... 
} finally { 
    // Clean up 
    session.Flush(); 
    session.Close(); 
} 

return return_value; 

모든 새로운 객체 (합니다 MyType)이 제대로 저장하지만 예상하는대로 user.field 상태가되지 않습니다 : 내가 삽입/개체를 저장하는 데 사용하는 패턴은 다음과 같다. obj.another_field도 정확합니다 (이 필드는 generated = on-save 정책이있는 ID 임).

'user.field = user.field - obj.field;'이 (가) 더 많이 필요한 횟수만큼 실행됩니다.

+0

이다 "mSession"와 "세션"같은 일? 나는 정적 인 것이 당신에게 어떤 문제를 일으킬 수 있다고 생각합니다. 실제로 많은 용도로 사용하기 위해 객체를 저장하는 코드를 볼 필요가 있습니다. – AlexCuse

답변

2

그것은 행동이 정말 무엇보다 많이 실행되고있는 것 같습니다 정말 이상해. 나는 그 반대를 기대할 것이다. 하지만 문제는 아니며 애플리케이션에 동시성 제어를 추가해 보겠습니다.

개체에 동시에 액세스하는 스레드 (낙관적 및 비관적) 간의 동시성을 제어하는 ​​몇 가지 옵션이 있습니다.

낙관적 인 컨트롤을 사용하면 개체를 저장하려고 할 때까지 세션이 작동하고 예외가 throw됩니다. 예외를 잡아서 처리하는 것은 사용자에게 매우 지루할 수 있습니다. 동일한 작업을 다시 수행하도록 요청해야하기 때문입니다. 그러나 동시 발생 문제가 발생하는 횟수가 상황에 의미가없는 경우, d 중 하나를 선택하십시오 : 응용 프로그램 전체 성능에 미치는 영향이 적습니다.

반대편에는 비관적 인 제어 기능이 있습니다. 이 경우 객체를 저장할 때 놀라지 않을 것이지만, 두 번째 세션은 작업을 진행할 때까지 첫 번째 세션이 트랜잭션을 커밋 할 때까지 기다려야합니다. 첫 번째 세션이 너무 오래 걸리는 경우 분명히 일종의 시간 초과 예외가 발생합니다. 규칙적인 시간이 걸리면 모든 것이 작동하지만 시스템에이 평균 속도에 잠금 시간이 걸립니다.


낙관적 - 옵션 1 : 업데이트되는 객체에 속성이 수정되기 이전 같은 값이있는 경우 NHibernate에 확인됩니다 있도록, 더러운 검사의 어떤 종류를 만들 수 있습니다. 차이가 있으면 예외가 발생합니다. DynamicUpdate가 NHibernate에 저장되는 속성 만이 아닌 전체 개체를 확인 말한다 활성화

 OptimisticLock.Dirty().DynamicUpdate(); 

: (유창함 NH 통해)를 구성하려면 비슷한 무언가를 추가해야 할 것입니다. OptimisticLock.All()을 사용하여 Hibernate가 모든 프로퍼티를 체크하도록 강제 할 수 있지만, 당신의 경우에는 필요하지 않다고 생각한다.

낙천주의 - 옵션 2 : 저장하려는 개체가 가장 최신인지 NH가 처리 할 Version 열을 명시 적으로 추가하는 옵션이 있습니다. 그렇지 않은 경우, 평소처럼 예외가 발생합니다. FluentNH 통해 구성하려면 :

 OptimisticLock.Version(); 
     Version(x => x.Version); // supposing that you have a Version property 

비관적 : 비관적 잠금이 당신의 get 메소드에서의 LockMode 열거를 통해 얻을 수있다. 이전에 말했듯이 소유자 세션이 트랜잭션을 커밋하기 전까지는 다른 세션에서 객체를 읽을 수 없습니다. 이 중 하나가 아마 당신의 문제를 해결하는 것입니다 접근법 사용

 MappedEntity ent1 = session1.Get<MappedEntity>(entity.Id, LockMode.Force); 

하지만 시나리오에서 각각의 장단점을 고려해이 같은 것을 사용합니다.

여기에 표시된 모든 정보는 Ayende의 블로그에서 적절한 HBM 매핑과 함께 사용할 수 있습니다. 다음을 참조하십시오 : http://ayende.com/Blog/archive/2009/04/15/nhibernate-mapping-concurrency.aspx

희망이 있으면 도움이 될 수 있으면 알려주세요.

감사합니다,

필리페

+0

지난 며칠 동안 나는 테스트를 반복해서 실행했습니다. 비관적 인 자물쇠로 문제가 해결되었지만 이상한 점은 LockMode.Upgrade 만 작동한다는 것입니다. 나는 PostgreSQL 8.3과 Mono 2.4.4에서 (LockMode.Force를 가지고 있지 않은) Hibernate 1.2를 사용하고 있습니다. 아마이 조합은 특정 수준에서 문제가 될 수 있습니다. NHibernate 2.0 또는 다른 구성 요소로 업데이트하면이 게시물을 업데이트해야한다는 것을 기억하려고합니다. Filipe, 빠르고 유익한 정보에 감사드립니다. –

+0

잠금 모드는 실제로 BD에서 BD로 변경 될 수 있습니다. 내 테스트 (실제로 내 경험)는 SQL Server를 기반으로합니다. 어쨌든 NH 버전을 업데이트하는 것이 좋습니다. – jfneis

0

연구원은

심지어 당신이 당신의 개체를 저장하는 데 사용하는 코드를 보지 않고, 서로 다른 통화 사이의 동일한 세션을 공유 할 수있는 좋은 방법이 아니다.

세션 팩토리는 매우 비용이 많이 드는 개체이며 메서드 특정 작업을 실행하지 않으므로 예를 들어 정적 변수를 사용하여 호출간에 공유하는 것이 좋습니다. 하지만 세션은 호출 컨텍스트 특정 객체입니다. 의심의 여지없이 하나의 세션/통화를 사용해야합니다.

정적 세션 개체의 동작을 변경하고 시도하십시오. 문제가 해결되지 않으면 코드 업데이트를 통해 개체를 업데이트하여보다 나은 결과를 얻을 수 있도록하십시오.

감사합니다,

필리페

관련 문제