1

複数のWCFサービスがすべてInstanceContextMode=PerCallで動作し、すべてのWCFサービスインスタンスはUnity(IOC)を使用してIInstanceProviderを実装することで生成されます。

相関識別子は、同じ識別子を持つすべてのメソッド呼び出しとデータベースプロセスを監査するために使用されます。

これを実現するために、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();
        }
    }

The problem here is the following; In some of the services, developers reported that the correlation identifier returns null. Since the problem is intermittant it is not possible to have a full stack trace at the moment. Also, they stated that reseting IIS resolves this problem temporarily.

Any help is appreciated...

4

3 に答える 3

1

Blamが提案したように、カスタムオブジェクトを格納する拡張機能を作成することにより、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参照を追加する必要があります。ドメインオブジェクトがサービスレイヤーにアクセスできるため、適切な方法ではないようですが、問題は解決しました。

于 2012-07-07T10:49:09.340 に答える
1

This doesn't really answer your question, and would have been a comment, except I wanted to have some code...

I am confused by your GetHeader method. Why are you doing a Linq .FirstOrDefault() on the dictionary, instead of just:

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

Aside from that, I don't actually see anything wrong with your code. I am curious as to where the developers are getting the null identifier. They would of course have to make sure they are on the same thread that the dispatcher was called on. If any async process, or ThreadPool was used anywhere to run something on another thread, then the [ThreadStatic] would not exist.

I had an issue once where I (very stupidly) referenced my [ThreadStatic] variable from a method that was called by a finalizer, which is run on the GC thread, so my thread static was always null. oops :)

于 2012-06-26T12:57:13.563 に答える
1

Several things: First, Your Threadstatic value creation is better implemented by ThreadLocal. This is basically the case whenever you need your threadstatic field to be initialized. Use

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

Second, for acquiring the value from the dictionary, what you're looking for is the TryGetValue method. I.e. not Contains-Get pair (as it does hash lookup twice unnecessary), and certainly not SingleOrDefault.

And third, to have a reliable ID identifying whatever happened from the one service call, just have it as one of the parameters of all the subsequent method calls.

于 2012-09-12T13:50:21.337 に答える