パフォーマンス上の理由から、オブジェクト階層をメモリ内にキャッシュする必要があります。これは、列(ObjectID、ParentObjectID、Timestamp)を含む単純なデータベーステーブルを反映し、CurrentObjectHierarchyを表示します。CurrentObjectHierarchyにクエリを実行し、ハッシュテーブルを使用して各オブジェクトの現在の親をキャッシュし、任意のオブジェクトIDを指定して親オブジェクトIDをすばやく検索します。データベーステーブルのクエリとキャッシュの構築は平均77ミリ秒の操作であり、理想的には、この更新は、階層を変更する(オブジェクトの追加/削除/親の変更)データベースAPIのメソッドが呼び出された場合にのみ発生します。
異なるアプリケーションプールで実行されている可能性のある複数のASP.NETWebアプリケーションからアクセスする必要がある場合、このようなキャッシュを配置するのに最適な場所はどこですか?
もともと、私はさまざまなWebアプリケーションで共有されているC#dllの静的変数にキャッシュを格納していました。もちろん、問題は、静的変数はスレッド間でアクセスできますが、プロセス間ではアクセスできないことです。これは、複数のWebアプリが関係している場合(おそらく別々のアプリケーションプールで実行されている場合)に問題になります。その結果、同じコードベースを使用している場合でも、あるアプリケーションのオブジェクト階層キャッシュに対する同期されたスレッドセーフな変更は、他のアプリケーションには反映されません。
したがって、このキャッシュにはよりグローバルな場所が必要です。静的変数(今説明したように)、セッション状態(基本的にはユーザーごとのストア)、およびアプリケーション状態(アプリケーション間でアクセス可能である必要があります)を使用できません。
私が検討している可能性のある場所は次のとおりです。
- IIS自体内のある種のグローバルオブジェクトストレージ。任意のアプリケーションプール内の任意のアプリケーションの任意のスレッドからアクセスできます(そのような場所が存在する場合。そうですか?)
- 排他的キャッシュを管理する別個のカスタムWebサービス。
今のところ、最善の解決策はSQLCLR統合だと思います。理由は次のとおりです。
- 静的変数を使用して現在の設計を維持できます
- すでに存在する別のサービスなので、カスタムサービスを作成する必要はありません
- 単一のプロセス(SQL Server)で実行されるため、既存のロックベースの同期は正常に機能します
- キャッシュは、それが表すデータ構造に可能な限り近く設定されます。
階層トラバースメソッドをSQLCLRDLLに埋め込んで、通常は通常のメソッド呼び出しを行う単一のSQL呼び出しを実行できるようにします。これはすべて、単一のプロセスで実行されているSQL Serverと、そのプロセスに読み込まれているCLRに依存します。これについてどう思いますか?私が行方不明になっているかもしれないというこの考えに明らかに間違っていることがわかりますか?これは素晴らしいアイデアではありませんか?
編集:詳しく調べてみると、さまざまなASP.NETアプリケーションが実際には同じプロセスで実行されているように見えますが、AppDomainによって分離されています。AppDomain間でデータを共有および同期する方法を見つけることができれば、それは非常に便利です。.NETRemotingについて読んでいます。