4

カスタム UsernamePasswordValidator を使用している WCF サービスがあります。バリデータはエンティティ フレームワーク コンテキストにアクセスする必要があります。

サービス呼び出し全体に対して 1 つの ObjectContext を作成し、呼び出しの最後に破棄/破棄したいと考えています。そこで、この機能を提供するシングルトン静的クラスを作成しましたが、現在起こっていることは、2 つのサービス呼び出しが同時に発生した場合、呼び出しの 1 つがシングルトンを破棄するということです。

ObjectContext へのローカル参照を保持します。この場合、それを使用する 2 番目のサービスはそれを破棄され、スローしてエラーと見なします。または、Singleton クラスの必要な場所にラッパー プロパティを配置し、すべての変更がスローされます。別の呼び出しがそれを破棄した場合、オブジェクトの新しいインスタンスを取得しているためです。

基本的に私の質問は、サービス呼び出しごとに ObjectContext をインスタンス化するにはどうすればよいですか?

注: インスタンスは、サービス コードとカスタム UsernamePasswordValidator コードの両方でアクセス可能である必要があります。

カスタム UsernamePasswordValidator はそれにアクセスできないため、コンストラクターでそれを実行したり、using ステートメントを使用したりすることはできません。呼び出しごとに静的クラスを持つ方法はありますか? それは不可能に聞こえますが、これを回避する方法は何ですか?セッションでオブジェクトをキャッシュする必要がありますか?

私のサービスは IIS でホストされています。

更新:
したがって、IExtension オブジェクトを使用して InstanceContext に状態を格納することにこれを釘付けにしました。しかし、UsernamePasswordValidator で現在の InstanceContext にアクセスするにはどうすればよいですか?

4

6 に答える 6

2

最後に、次の静的クラスを使用し、ASP.NET に依存してコンテキストをキャッシュすることで解決しました。

これが最善の方法かどうかはわかりませんが、これにより、リクエストごとに 1 つの ObjectContext を使用できるため、スピンアップしすぎず、オブジェクトのロックを使用する必要もありません。多くのユーザーがサービスを使用していると、これは悪夢になります。

public static class MyContextProvider
    {
        public static MyModel Context
        {
            get
            {
                if (HttpContext.Current.Items["context"].IsNull())
                {
                    HttpContext.Current.Items["context"] = new MyModel();
                }

                return HttpContext.Current.Items["context"] as MyModel;
            }
        }    
    }

次に、アプリで ObjectContext が必要な場所で、呼び出すだけです

var context = MyContextProvider.Context;
于 2010-07-23T10:55:04.417 に答える
1

呼び出しごとに 1 つのインスタンスがあり、インスタンスごとに 1 つの呼び出しもあります。

using () { }したがって、OperationContract メソッドのトップレベルでブロックを使用して、非常に単純にする必要があります。

于 2010-07-23T09:48:18.750 に答える
1

OK、これはスレッドセーフな静的メソッドを持つクラスで、WCF サービス呼び出しに対して単一の ObjectContext エンティティ モデル オブジェクトを提供し、呼び出しの最後に自動的に破棄します。

public static class EntityModelProvider
{
    private static readonly Dictionary<OperationContext, MyEntityModel> _entityModels = new Dictionary<OperationContext, MyEntityModel>();

    public static MyEntityModel GetEntityModel()
    {
        if (OperationContext.Current == null)
            throw new Exception("OperationContext is missing");

        lock (_entityModels)
        {
            if (!_entityModels.ContainsKey(OperationContext.Current))
            {
                _entityModels[OperationContext.Current] = new MyEntityModel();
                OperationContext.Current.OperationCompleted += delegate
                {
                    lock (_entityModels)
                    {
                        _entityModels[OperationContext.Current].Dispose();
                        _entityModels.Remove(OperationContext.Current);
                    }
                };
            }

            return _entityModels[OperationContext.Current];
        }
    }
于 2013-08-02T20:17:55.720 に答える
0

サービスに対して、サービスのインスタンス モードを詳述するサービス動作を指定できます。

[ServiceBehaviour(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService : IMyService {
    ObjectContext context;
}
于 2010-07-23T09:46:07.127 に答える
0

よりクリーンな方法は、.NET 4 にある ServiceAuthenticationManager を使用することです。

http://msdn.microsoft.com/en-us/library/system.servicemodel.serviceauthenticationmanager.aspx

メソッド (オーバーライドする)からAuthenticateMessage オブジェクトにアクセスし、そのプロパティを設定できます。私は怒りでそれを使用していないので、YMMV :)

編集 このアプローチの問題は、ユーザー名とパスワードがないため、カスタム認証が必要になることです。

UsernameSecurityTokenAuthenticator を見てください... http://msdn.microsoft.com/en-us/library/system.identitymodel.selectors.usernamesecuritytokenauthenticator(v=vs.90).aspx


私の研究からさらに読む:

この質問への回答は、使用方法に関するいくつかのヒントを提供します。

System.ServiceModel.ServiceAuthenticationManager を使用したカスタム WCF 認証?

ロシア語が読める (または無視できる) 場合は、次の場所に役立つヒントを見つけました。

http://www.sql.ru/forum/actualthread.aspx?tid=799046

このかなり優れた CodeProject の記事はさらに進んでいます (暗号化と圧縮、およびカスタム認証)。

http://www.codeproject.com/Articles/165844/WCF-Client-Server-Application-with-Custom-Authenti

于 2012-12-12T15:54:29.767 に答える