どのSQLEdendencyが変更機能を引き起こしたかを理解する方法
-
11-12-2019 - |
質問
SQLDependency
クラスを使用してクエリ通知を探索しています。簡単な例を構築するのは簡単ですが、私は何かが足りないように感じます。簡単な1テーブル/ 1依存的な例を過ぎると、私はどの依存関係を引き起こしたかを理解できるのですか?
私は何度も説明しているので、以下の単純な例を含めました。 AChange()
と呼ばれると、依存関係内でSQLを調べることはできません。関連するキャッシュオブジェクトへの参照はありません。
だから男の子は何をするのですか?
- オプション1 - キャッシュキー(または関連情報)をキャッシュバックで追跡してハードコーディングしたいオブジェクトごとに異なる関数を作成します。これは汚れを感じて新しいコードを展開せずに新しいキャッシュ項目を追加する能力を排除します。
- オプション2 - 依存関係
Id
プロパティと並列追跡構造体を使用する私はただ何か不足していますか?これは
SQLDependency
構造の欠陥ですか?私はトピック上の20種類の記事を見ました、そしてそれらのすべてが同じ穴を持っているようです。提案?コードサンプル
.public class DependencyCache{ public static string cacheName = "Client1"; public static MemoryCache memCache = new MemoryCache(cacheName); public DependencyCache() { SqlDependency.Start(connString); } private static string GetSQL() { return "select someString FROM dbo.TestTable"; } public void DoTest() { if (memCache["TEST_KEY"] != null ) { Debug.WriteLine("resources found in cache"); return; } Cache_GetData(); } private void Cache_GetData() { SqlConnection oConn; SqlCommand oCmd; SqlDependency oDep; SqlDataReader oRS; List<string> stuff = new List<string>(); CacheItemPolicy policy = new CacheItemPolicy(); SqlDependency.Start(connString); using (oConn = new SqlConnection(connString) ) { using (oCmd = new SqlCommand(GetSQL(), oConn) ) { oDep = new SqlDependency(oCmd); oConn.Open(); oRS = oCmd.ExecuteReader(); while(oRS.Read() ) { resources.Add( oRS.GetString(0) ); } oDep.OnChange += new OnChangeEventHandler (AChange); } } memCache.Set("TEST_KEY", stuff, policy); } private void AChange( object sender, SqlNotificationEventArgs e) { string msg= "Dependency Change \nINFO: {0} : SOURCE {1} :TYPE: {2}"; Debug.WriteLine(String.Format(msg, e.Info, e.Source, e.Type)); // If multiple queries use this as a callback how can i figure // out WHAT QUERY TRIGGERED the change? // I can't figure out how to tell multiple dependency objects apart ((SqlDependency)sender).OnChange -= Cache_SqlDependency_OnChange; Cache_GetData(); //reload data } }
解決
最初と中間:ハンドラはの前に設定されなければなりませんコマンドが実行されます:
.
oDep = new SqlDependency(oCmd);
oConn.Open();
oDep.OnChange += new OnChangeEventHandler (AChange);
oRS = oCmd.ExecuteReader();
while(oRS.Read() ) {
resources.Add( oRS.GetString(0) );
}
それ以外の場合は、通知が失われたときにウィンドウがあり、コールバックが発生しないようになります。
あなたの質問について:クエリごとに別のコールバックを使用する必要があります。これは面倒なように見えるかもしれませんが、実際にはラムダを使って些細なことです。次のようなもの:
.
oDep = new SqlDependency(oCmd);
oConn.Open();
oDep.OnChange += (sender, e) =>
{
string msg = "Dependency Change \nINFO: {0} : SOURCE {1} :TYPE: {2}";
Debug.WriteLine(String.Format(msg, e.Info, e.Source, e.Type));
// The command that trigger the notification is captured in the context:
// is oCmd
//
// You can now call a handler passing in the relevant info:
//
Reload_Data(oCmd, ...);
};
oRS = oCmd.ExecuteReader();
...
常にの通知元、情報と種類を確認してください。そうでなければ、無効なクエリのように、データ変更よりも を通知されたときにAD-NAUSEAMを回転させるリスクを実行します。サイドコメントとして、良いキャッシュデザインが無効化のキャッシュを更新しないことを追加しますが、キャッシュされたアイテムを無効にして、のリクエストが実際に新たなアイテムを取得できるようにします。あなたの「Proactive」アプローチで、必要でない場合はキャッシュされたアイテムを更新し、アクセスされる前に複数回更新されます。エラー処理の例と適切なスレッド同期(両方とも必要)を省略しました。
最後に、 linqtocache を見てください。するが、LINQクエリのために。