ASP.NET アプリケーションでの SqlDependency
この記事の例は、ASP.NET SqlCacheDependency オブジェクトを利用して SqlDependency を間接的に使用する方法を示しています。 SqlCacheDependency オブジェクトでは SqlDependency を使用して通知をリッスンし、キャッシュを適切に更新します。
Note
このサンプル コードを実行するには、「クエリ通知の有効化」のスクリプトを実行してクエリ通知を有効にしておく必要があります。
サンプル アプリケーションについて
このサンプル アプリケーションでは、1 つの ASP.NET Web ページを使用して、SQL Server データベースである AdventureWorks に格納されている製品情報を GridView コントロールに表示します。 ページが読み込まれる際に、コードによって Label コントロールに現在の時刻が書き込まれます。 次に、SqlCacheDependency オブジェクトが定義され、最大 3 分間キャッシュ データが格納されるように Cache オブジェクトのプロパティが設定されます。 その後、データベースに接続され、データが取得されます。 ページが読み込まれ、アプリケーションが実行されると、ASP.NET によって、データがキャッシュから取得されます。これは、ページ上の時刻が変更されないことで確認できます。 監視しているデータが変化すると、ASP.NET によりキャッシュが無効化され、GridView
コントロールに最新データが再入力されることで、Label
コントロールに表示される時刻が更新されます。
サンプル アプリケーションの作成
サンプル アプリケーションを作成して実行するには、次の手順に従います。
新しい ASP.NET Web サイトを作成します。
ページのクラス モジュールを開き、次のディレクティブを追加します。
Option Strict On Option Explicit On Imports System.Data.SqlClient
using System.Data.SqlClient; using System.Web.Caching;
次のコードをページの
Page_Load
イベントに追加します。protected void Page_Load(object sender, EventArgs e) { Label1.Text = "Cache Refresh: " + DateTime.Now.ToLongTimeString(); // Create a dependency connection to the database. SqlDependency.Start(GetConnectionString()); using (SqlConnection connection = new SqlConnection(GetConnectionString())) { using (SqlCommand command = new SqlCommand(GetSQL(), connection)) { SqlCacheDependency dependency = new SqlCacheDependency(command); // Refresh the cache after the number of minutes // listed below if a change does not occur. // This value could be stored in a configuration file. int numberOfMinutes = 3; DateTime expires = DateTime.Now.AddMinutes(numberOfMinutes); Response.Cache.SetExpires(expires); Response.Cache.SetCacheability(HttpCacheability.Public); Response.Cache.SetValidUntilExpires(true); Response.AddCacheDependency(dependency); connection.Open(); GridView1.DataSource = command.ExecuteReader(); GridView1.DataBind(); } } }
Protected Sub Page_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Load Label1.Text = "Cache Refresh: " & _ Date.Now.ToLongTimeString() ' Create a dependency connection to the database SqlDependency.Start(GetConnectionString()) Using connection As New SqlConnection(GetConnectionString()) Using command As New SqlCommand(GetSQL(), connection) Dim dependency As New SqlCacheDependency(command) ' Refresh the cache after the number of minutes ' listed below if a change does not occur. ' This value could be stored in a configuration file. Dim numberOfMinutes As Integer = 3 Dim expires As Date = _ DateTime.Now.AddMinutes(numberOfMinutes) Response.Cache.SetExpires(expires) Response.Cache.SetCacheability(HttpCacheability.Public) Response.Cache.SetValidUntilExpires(True) Response.AddCacheDependency(dependency) connection.Open() GridView1.DataSource = command.ExecuteReader() GridView1.DataBind() End Using End Using End Sub
GetConnectionString
およびGetSQL
という 2 つのヘルパー メソッドを追加します。 定義される接続文字列は、統合セキュリティを利用します。 使用しているアカウントが、必要とされるデータベースへのアクセス許可を持っており、サンプル データベースの AdventureWorks で通知が有効になっていることを確認する必要があります。private string GetConnectionString() { // To avoid storing the connection string in your code, // you can retrieve it from a configuration file. return "Data Source=(local);Integrated Security=true;" + "Initial Catalog=AdventureWorks;"; } private string GetSQL() { return "SELECT Production.Product.ProductID, " + "Production.Product.Name, " + "Production.Location.Name AS Location, " + "Production.ProductInventory.Quantity " + "FROM Production.Product INNER JOIN " + "Production.ProductInventory " + "ON Production.Product.ProductID = " + "Production.ProductInventory.ProductID " + "INNER JOIN Production.Location " + "ON Production.ProductInventory.LocationID = " + "Production.Location.LocationID " + "WHERE ( Production.ProductInventory.Quantity <= 100 ) " + "ORDER BY Production.ProductInventory.Quantity, " + "Production.Product.Name;"; }
Private Function GetConnectionString() As String ' To avoid storing the connection string in your code, ' you can retrieve it from a configuration file. Return "Data Source=(local);Integrated Security=true;" & _ "Initial Catalog=AdventureWorks;" End Function Private Function GetSQL() As String Return "SELECT Production.Product.ProductID, " & _ "Production.Product.Name, " & _ "Production.Location.Name AS Location, " & _ "Production.ProductInventory.Quantity " & _ "FROM Production.Product INNER JOIN " & _ "Production.ProductInventory " & _ "ON Production.Product.ProductID = " & _ "Production.ProductInventory.ProductID " & _ "INNER JOIN Production.Location " & _ "ON Production.ProductInventory.LocationID = " & _ "Production.Location.LocationID " & _ "WHERE ( Production.ProductInventory.Quantity <= 100) " & _ "ORDER BY Production.ProductInventory.Quantity, " & _ "Production.Product.Name;" End Function
重要
Microsoft では、使用可能な最も安全な認証フローを使用することをお勧めします。 Azure SQL に接続する場合は、Azure リソースの管理 ID が推奨される認証方法です。
アプリケーションのテスト
このアプリケーションは Web フォームに表示されるデータをキャッシングし、操作が行われなければ 3 分ごとにデータを更新します。 データベースに変更があれば、キャッシュは直ちに更新されます。 Visual Studio からアプリケーションを実行すると、ブラウザーにページが読み込まれます。 表示されるキャッシュ更新時刻は、最後にキャッシュが更新された時刻を示します。 3 分間の待機後、ページを更新すると、ポストバック イベントが発生します。 ページに表示される時刻が変更されることに注意してください。 3 分経過する前にページを更新した場合、ページに表示される時刻は変わりません。
次に、Transact-SQL の UPDATE コマンドを使用して、データベースのデータを更新し、ページを更新します。 表示される時刻を見ると、データベースの新しいデータを使ってキャッシュが更新されたことがわかります。 キャッシュは更新されますが、ページに表示される時刻はポストバック イベントが発生するまで変更されないことに注意してください。
SQL の依存関係を使用した分散キャッシュの同期
NCache などの一部のサードパーティの分散キャッシュでは、SQL の依存関係を使用した SQL データベースとキャッシュの同期がサポートされています。 詳細とソース コード実装の例については、分散キャッシュの SQL の依存関係のサンプルに関するページを参照してください。