2012-06-26 3 views
0

우리는 모두 InstanceContextMode = PerCall과 함께 작동하는 여러 WCF 서비스를 가지고 있으며 모든 WCF 서비스 인스턴스는 Unity (IOC)를 사용하고 IInstanceProvider를 구현하여 생성됩니다.WCF Percall 모드 및 스레드 고정 변수

상관 ID는 동일한 ID로 모든 메소드 호출 및 데이터베이스 프로세스를 감사하는 데 사용됩니다.

이렇게하기 위해 IDispatchBehavior를 구현하여 끝점 동작을 만들고 AfterReceiveRequest 메서드에서 GUID를 생성하고 ThreadStatic (CommonData) 속성에 할당합니다. 이 속성은 응용 프로그램의 모든 레이어에서 액세스 할 수 있습니다. 다음 코드 블록은 CommonData 및 CommonData 클래스의 채우기를 보여줍니다.

public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) 
     { 
      CommonData.ClearDictionary(); 
      //the lines between are deleted as they are not relevant to the question 

      CommonData.Current.Add(MessageHeaderCodes.CorrelationId, Guid.NewGuid().ToString());  
      return null; 
     } 

및 commondata 클래스 :

public class CommonData 
    {    
     [ThreadStatic] 
     private static Dictionary<string, string> headerData;  

     public static Dictionary<string, string> Current 
     { 
      get 
      { 
       if (headerData == null) 
       { 
        headerData = new Dictionary<string, string>(); 
       } 
       return headerData; 
      }    
     } 

     private CommonData() 
     { 

     } 

     public static string GetHeader(string header) 
     { 
      string headerValue = string.Empty; 
      KeyValuePair<string, string> headerKeyValuePair = CommonData.Current.SingleOrDefault(p => p.Key == header); 
      headerValue = headerKeyValuePair.Value; 
      return headerValue; 
     } 

     public static void ClearDictionary() 
     { 
      Current.Clear(); 
     } 
    } 

여기서 문제는 다음과 같다; 일부 서비스에서 개발자는 상관 식별자가 null을 반환한다고보고했습니다. 문제가 간헐적이기 때문에 현재 전체 스택 추적을 가질 수 없습니다. 또한 IIS를 다시 설정하면이 문제가 일시적으로 해결됩니다. 내가 혼란스러워하고

나는 몇 가지 코드를하고 싶었을 제외하고이 정말 귀하의 질문에 대답하지 않고, 코멘트했을

+0

식별자를 검색하는 방법 (GetHeader 메서드로 추측)은 무엇입니까? – Bond

+0

클라이언트에서 식별자를 얻지 못했습니다. 각 호출에 대해 AfterReceiveRequest 메서드에서 새 식별자를 만듭니다. CommonData.Current.Add (MessageHeaderCodes.CorrelationId, Guid.NewGuid(). ToString()); – daryal

+0

네,하지만 어떻게 든 나중에 다시 검색하려고합니까? 방법? 그렇지 않다면 - 정확히 null이 무엇입니까? 사실 정확한 질문 인 – Bond

답변

1

Blam이 제안했듯이 사용자 지정 개체를 저장하기 위해 Extension을 작성하여 OperationContext.Current를 사용했습니다. 아래는 확장자입니다.

public class OperationContextExtension : IExtension<OperationContext> 
{ 
    public void Attach(OperationContext owner) 
    { 
     this.Current = new Dictionary<string, string>(); 
    } 

    public void Detach(OperationContext owner) 
    { 
     this.Current = null; 
    } 

    public Dictionary<string,string> Current { get; set; } 
} 

한편, 도메인 개체에 System.ServiceModel 참조를 추가해야합니다. 도메인 개체가 서비스 계층에 액세스 할 수있는 적절한 방법이 아닌 것 같지만 문제가 해결되었습니다.

1

어떤 도움에 감사드립니다

... ... 당신의 GetHeader 메서드. 왜 당신은 대신에, 사전에 Linq에 .FirstOrDefault()을하고있다 : 그 외에

public static string GetHeader(string header) 
{ 
    if(CommonData.Current.ContainsKey(header)) 
     return CommonData.Current[header]; 
    return null; 
} 

, 나는 실제로 코드를 잘못 아무것도 표시되지 않습니다. 개발자가 null 식별자를 얻는 곳이 궁금합니다. 그들은 물론 디스패처가 호출 된 것과 동일한 스레드에 있는지 확인해야합니다. 비동기 프로세스 또는 ThreadPool이 다른 스레드에서 어떤 것을 실행하기 위해 사용 된 경우 [ThreadStatic]은 존재하지 않습니다.

나는 (매우 어리석게도) 내 [ThreadStatic] 변수를 GC 스레드에서 실행되는 finalizer에 의해 호출 된 메서드에서 참조 했으므로 문제가 발생하여 내 스레드 정적이 항상 null이되었습니다. oops :)

+0

첫 번째 기본 댓글에 맞습니다. headerKeyValuePair가 null 인 경우 예외가 발생할 수 있으므로 업데이트 할 예정입니다. 개발자는 비즈니스 관련 코드에서 null 값을 얻고 있습니다. 어쩌면 구조에 대한 더 자세한 정보를 제공하는 것이 더 좋을지 모르지만, 나는 아주 간단한 것을 놓친 것 같았습니다. 질문을 업데이트하려고합니다 ... – daryal

1

몇 가지 : 먼저 Threadstatic에 의해 Threadstatic 값 생성이 더 잘 구현됩니다. threadstatic 필드를 초기화해야 할 때마다 기본적으로 적용됩니다.

private static ThreadStatic<Dictionary<string, string>> headerData = new ThreadStatic<Dictionary<string, string>>(() => new Dictionary<string, string>()); 

둘째, 사전에서 값을 얻으려면 TryGetValue 메서드를 사용하십시오. 나는. Not Contains- 쌍을 얻습니다 (해시 조회가 두 번 필요하지 않음). 물론 SingleOrDefault가 아닙니다.

세 번째, 한 서비스 호출에서 발생한 모든 것을 식별하는 신뢰할 수있는 ID를 갖기 위해서는 모든 후속 메서드 호출의 매개 변수 중 하나로 지정하십시오.