アプリケーションの起動時にデータをキャッシュする (VB)
Web アプリケーションでは、一部のデータが頻繁に使用され、一部のデータは頻繁に使用されません。 頻繁に使用されるデータ (と呼ばれる手法) を事前に読み込むことで、ASP.NET アプリケーションのパフォーマンスを向上させることができます。 このチュートリアルでは、プロアクティブ読み込みの 1 つの方法を示します。これは、アプリケーションの起動時にキャッシュにデータを読み込む方法です。
はじめに
前の 2 つのチュートリアルでは、プレゼンテーション レイヤーとキャッシュ レイヤーでのデータのキャッシュについて説明しました。 「ObjectDataSource を使用したデータのキャッシュ」では、ObjectDataSource のキャッシュ機能を使用してプレゼンテーション レイヤー内のデータをキャッシュする方法について説明しました。 アーキテクチャ内のデータのキャッシュ では、新しい個別のキャッシュ レイヤーでのキャッシュが調べられた。 これらのチュートリアルではどちらも、データ キャッシュの操作で 事後対応型の読み込みを 使用しました。 事後対応型の読み込みでは、データが要求されるたびに、システムは最初にキャッシュ内にあるかどうかを確認します。 そうでない場合は、データベースなどの元のソースからデータを取得し、キャッシュに格納します。 反応性読み込みのメイン利点は、実装の容易さです。 その欠点の 1 つは、要求間でパフォーマンスが不均等になることです。 前のチュートリアルのキャッシュ レイヤーを使用して製品情報を表示するページを想像してみてください。 このページが初めてアクセスされたとき、またはメモリ制約または指定された有効期限に達したためにキャッシュされたデータが削除された後に初めてアクセスした場合は、データベースからデータを取得する必要があります。 したがって、これらのユーザー要求は、キャッシュで提供できるユーザー要求よりも時間がかかります。
プロアクティブ読み込みは 、必要になる前にキャッシュされたデータを読み込むことで、要求全体のパフォーマンスを滑らかにする代替キャッシュ管理戦略を提供します。 通常、プロアクティブ読み込みでは、基になるデータの更新が行われたときに定期的にチェックされるか通知されるプロセスが使用されます。 このプロセスでは、キャッシュが最新の状態に保たれ、更新されます。 プロアクティブ読み込みは、基になるデータが低速なデータベース接続、Web サービス、またはその他の特に低速なデータ ソースから取得される場合に特に便利です。 ただし、プロアクティブ読み込みに対するこのアプローチは、変更をチェックしてキャッシュを更新するためのプロセスを作成、管理、デプロイする必要があるため、実装が困難になります。
プロアクティブ読み込みのもう 1 つのフレーバーと、このチュートリアルで説明する種類は、アプリケーションの起動時にキャッシュにデータを読み込む方法です。 この方法は、データベース参照テーブルのレコードなどの静的データをキャッシュする場合に特に便利です。
注意
プロアクティブ読み込みと事後対応読み込みの違いと、長所、短所、実装に関する推奨事項の一覧については、「.NET Framework アプリケーションのキャッシュ アーキテクチャ ガイド」の「キャッシュの内容の管理」セクションを参照してください。
手順 1: アプリケーションの起動時にキャッシュするデータを決定する
前の 2 つのチュートリアルで調べた事後対応型読み込みを使用したキャッシュの例は、定期的に変更される可能性があり、生成に法外に長い時間はかからず、データとうまく連携します。 ただし、キャッシュされたデータが変更されない場合、リアクティブ読み込みによって使用される有効期限は余分です。 同様に、キャッシュされるデータの生成に非常に長い時間がかかる場合、キャッシュが空であると見なされる要求を持つユーザーは、基になるデータの取得中に長い待機に耐える必要があります。 アプリケーションの起動時に生成するのに非常に長い時間がかかる静的データとデータをキャッシュすることを検討してください。
データベースには動的で頻繁に変化する値が多数ありますが、ほとんどの場合、静的データも大量に含まれています。 たとえば、事実上すべてのデータ モデルには、固定された選択肢セットの特定の値を含む 1 つ以上の列があります。 Patients
データベース テーブルには列がありPrimaryLanguage
、値のセットは英語、スペイン語、フランス語、ロシア語、日本語などです。 多くの場合、これらの種類の列は 参照テーブルを使用して実装されます。 テーブルに英語またはフランス語 Patients
の文字列を格納するのではなく、一般的に 2 つの列 (一意識別子と文字列の説明) を持つ 2 つ目のテーブルが作成され、使用可能な値ごとにレコードが含まれます。 テーブル内の列には PrimaryLanguage
、 Patients
対応する一意識別子が参照テーブルに格納されます。 図 1 では、患者の John Doe の第一言語は英語で、Ed Johnson s はロシア語です。
図 1: テーブルは Languages
テーブルで Patients
使用される参照テーブルです
新しい患者を編集または作成するためのユーザー インターフェイスには、テーブル内のレコードによって設定された許容言語のドロップダウン リストが Languages
含まれます。 キャッシュを使用しない場合、このインターフェイスにアクセスするたびに、システムはテーブルに対してクエリを実行する Languages
必要があります。 ルックアップ テーブルの値は変更される頻度が非常に低いため、これは無駄で不要です。
前のチュートリアルで Languages
調べたのと同じ事後対応読み込み手法を使用して、データをキャッシュできます。 ただし、事後対応読み込みでは時間ベースの有効期限が使用されます。これは静的参照テーブル データには必要ありません。 リアクティブ読み込みを使用したキャッシュはキャッシュをまったく行っていないよりも優れていますが、最適な方法は、アプリケーションの起動時に参照テーブル のデータをキャッシュに事前に読み込む方法です。
このチュートリアルでは、参照テーブル データとその他の静的な情報をキャッシュする方法について説明します。
手順 2: データをキャッシュするさまざまな方法を調べる
情報は、さまざまな方法を使用して ASP.NET アプリケーションにプログラムでキャッシュできます。 前のチュートリアルでは、データ キャッシュの使用方法を既に確認しました。 または、 静的メンバー または アプリケーションの状態を使用して、オブジェクトをプログラムでキャッシュすることもできます。
クラスを操作する場合、通常、メンバーにアクセスするには、まず クラスをインスタンス化する必要があります。 たとえば、ビジネス ロジック レイヤーのいずれかのクラスからメソッドを呼び出すには、まず クラスのインスタンスを作成する必要があります。
Dim productsAPI As New ProductsBLL()
productsAPI.SomeMethod()
productsAPI.SomeProperty = "Hello, World!"
SomeMethod を呼び出したり、SomeProperty を操作したりする前に、まず、キーワード (keyword)を使用して クラスのインスタンスを作成するNew
必要があります。 SomeMethod と SomeProperty は、特定のインスタンスに関連付けられます。 これらのメンバーの有効期間は、関連付けられているオブジェクトの有効期間に関連付けられます。 一方、静的メンバーは、クラスのすべてのインスタンス間で共有される変数、プロパティ、およびメソッドであり、したがって、 クラスと同じ有効期間を持ちます。 静的メンバーは、 キーワード (keyword) Shared
で示されます。
静的メンバーに加えて、アプリケーションの状態を使用してデータをキャッシュできます。 各 ASP.NET アプリケーションは、アプリケーションのすべてのユーザーとページで共有される名前/値コレクションを保持します。 このコレクションには、 クラスの Application
プロパティをHttpContext
使用してアクセスでき、次のように ASP.NET ページの分離コード クラスから使用できます。
Application("key") = value
Dim value As Object = Application("key")
データ キャッシュは、データをキャッシュするためのより豊富な API を提供し、時間と依存関係に基づく有効期限、キャッシュ 項目の優先順位などのメカニズムを提供します。 静的メンバーとアプリケーションの状態では、このような機能をページ開発者が手動で追加する必要があります。 ただし、アプリケーションの起動時にアプリケーションの有効期間中にデータをキャッシュする場合、データ キャッシュの利点は問題になります。 このチュートリアルでは、静的データをキャッシュするために 3 つの手法をすべて使用するコードについて説明します。
手順 3: テーブル データのSuppliers
キャッシュ
これまでに実装した Northwind データベース テーブルには、従来の参照テーブルは含まれていません。 DAL に実装されている 4 つの DataTable は、非静的な値を持つすべてのモデル テーブルです。 このチュートリアルでは、新しい DataTable を DAL に追加し、新しいクラスとメソッドを BLL に追加する時間を費やすのではなく、テーブルのデータが静的であるふりを Suppliers
してみましょう。 そのため、アプリケーションの起動時にこのデータをキャッシュできます。
開始するには、 フォルダーに という名前 StaticCache.cs
の新しいクラスを CL
作成します。
図 2: フォルダーにクラスをStaticCache.vb
作成するCL
起動時にデータを適切なキャッシュ ストアに読み込むメソッドと、このキャッシュからデータを返すメソッドを追加する必要があります。
<System.ComponentModel.DataObject()> _
Public Class StaticCache
Private Shared suppliers As Northwind.SuppliersDataTable = Nothing
Public Shared Sub LoadStaticCache()
' Get suppliers - cache using a static member variable
Dim suppliersBLL As New SuppliersBLL()
suppliers = suppliersBLL.GetSuppliers()
End Sub
<DataObjectMethodAttribute(DataObjectMethodType.Select, True)> _
Public Shared Function GetSuppliers() As Northwind.SuppliersDataTable
Return suppliers
End Function
End Class
上記のコードでは、静的メンバー変数 を使用して、 suppliers
メソッドから SuppliersBLL
呼び出されるクラス s GetSuppliers()
メソッドの結果を LoadStaticCache()
保持します。 メソッドは LoadStaticCache()
、アプリケーションの起動時に呼び出されることを意図しています。 このデータがアプリケーションの起動時に読み込まれたら、サプライヤー データを操作する必要があるページでクラスの GetSuppliers()
メソッドをStaticCache
呼び出すことができます。 したがって、仕入先を取得するためのデータベースの呼び出しは、アプリケーションの開始時に 1 回だけ行われます。
静的メンバー変数をキャッシュ ストアとして使用するのではなく、アプリケーションの状態またはデータ キャッシュを使用することもできます。 次のコードは、アプリケーションの状態を使用するように再ツールされたクラスを示しています。
<System.ComponentModel.DataObject()> _
Public Class StaticCache
Public Shared Sub LoadStaticCache()
' Get suppliers - cache using application state
Dim suppliersBLL As New SuppliersBLL()
HttpContext.Current.Application("key") = suppliers
End Sub
<DataObjectMethodAttribute(DataObjectMethodType.Select, True)> _
Public Shared Function GetSuppliers() As Northwind.SuppliersDataTable
Return TryCast(HttpContext.Current.Application("key"), _
Northwind.SuppliersDataTable)
End Function
End Class
では LoadStaticCache()
、サプライヤー情報がアプリケーション変数 キーに格納されます。 から適切な型 (Northwind.SuppliersDataTable
) GetSuppliers()
として返されます。 アプリケーションの状態は、 を使用して Application("key")
ASP.NET ページの分離コード クラスでアクセスできますが、アーキテクチャでは、現在HttpContext
の を取得するために を使用HttpContext.Current.Application("key")
する必要があります。
同様に、次のコードに示すように、データ キャッシュをキャッシュ ストアとして使用できます。
<System.ComponentModel.DataObject()> _
Public Class StaticCache
Public Shared Sub LoadStaticCache()
' Get suppliers - cache using a static member variable
Dim suppliersBLL As New SuppliersBLL()
HttpRuntime.Cache.Insert("key", suppliers, Nothing, _
Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, _
CacheItemPriority.NotRemovable, Nothing)
End Sub
<System.ComponentModel.DataObjectMethodAttribute_
(System.ComponentModel.DataObjectMethodType.Select, True)> _
Public Shared Function GetSuppliers() As Northwind.SuppliersDataTable
Return TryCast(HttpRuntime.Cache("key"), Northwind.SuppliersDataTable)
End Function
End Class
時間ベースの有効期限のない項目をデータ キャッシュに追加するには、 と System.Web.Caching.Cache.NoSlidingExpiration
の値をSystem.Web.Caching.Cache.NoAbsoluteExpiration
入力パラメーターとして使用します。 キャッシュ 項目の優先度を指定できるように、データ キャッシュのInsert
メソッドのこの特定のオーバーロードが選択されました。 優先度は、使用可能なメモリが不足しているときにキャッシュからスカベンジする項目を決定するために使用されます。 ここでは、優先度 NotRemovable
を使用します。これにより、このキャッシュ項目が清掃されないようにします。
注意
このチュートリアルのダウンロードでは、静的メンバー変数のアプローチを使用して クラスを実装します StaticCache
。 アプリケーションの状態とデータ キャッシュ手法のコードは、クラス ファイルのコメントで使用できます。
手順 4: アプリケーションの起動時にコードを実行する
Web アプリケーションが最初に起動したときにコードを実行するには、 という名前 Global.asax
の特別なファイルを作成する必要があります。 このファイルには、アプリケーション、セッション、および要求レベルのイベントのイベント ハンドラーを含めることができます。ここでは、アプリケーションの起動時に実行されるコードを追加できます。
Visual Studio の Global.asax
ソリューション エクスプローラーで Web サイト プロジェクト名を右クリックし、[新しい項目の追加] を選択して、Web アプリケーションのルート ディレクトリにファイルを追加します。 [新しい項目の追加] ダイアログ ボックスで、[グローバル アプリケーション クラス] 項目の種類を選択し、[追加] ボタンをクリックします。
注意
プロジェクトにファイルが Global.asax
既にある場合、[グローバル アプリケーション クラス] 項目の種類は [新しい項目の追加] ダイアログ ボックスに表示されません。
図 3: Web アプリケーションの Global.asax
ルート ディレクトリにファイルを追加する (クリックするとフルサイズの画像が表示されます)
既定 Global.asax
のファイル テンプレートには、サーバー側 <script>
タグ内に 5 つのメソッドが含まれています。
Application_Start
は、Web アプリケーションが最初に起動したときに実行されますApplication_End
アプリケーションのシャットダウン時に実行されるApplication_Error
ハンドルされない例外がアプリケーションに到達するたびに実行されますSession_Start
は、新しいセッションの作成時に実行されますSession_End
セッションが期限切れまたは破棄されたときに実行される
イベント ハンドラーは Application_Start
、アプリケーションのライフ サイクル中に 1 回だけ呼び出されます。 アプリケーションは、ASP.NET リソースがアプリケーションから初めて要求されるときに起動し、アプリケーションが再起動されるまで実行を続けます。これは、フォルダーの内容の変更、フォルダー内の内容App_Code
の変更Global.asax
、ファイルの/Bin
変更Web.config
などによって発生する可能性があります。 アプリケーションのライフ サイクルの詳細については、「ASP.NET アプリケーション ライフ サイクルの概要」を参照してください。
これらのチュートリアルでは、 メソッドにコードを追加するだけで Application_Start
済むので、他のコードを自由に削除してください。 ではApplication_Start
、 クラスの LoadStaticCache()
メソッドをStaticCache
呼び出すだけで、サプライヤー情報を読み込んでキャッシュします。
<%@ Application Language="VB" %>
<script runat="server">
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
StaticCache.LoadStaticCache()
End Sub
</script>
それはそれのすべてです! アプリケーションの起動時に LoadStaticCache()
、メソッドは BLL からサプライヤー情報を取得し、静的メンバー変数 (またはクラスで使用したキャッシュ ストア) に StaticCache
格納します。 この動作を確認するには、 メソッドにブレークポイントを Application_Start
設定し、アプリケーションを実行します。 ブレークポイントは、アプリケーションの起動時にヒットすることに注意してください。 ただし、後続の要求では、 メソッドは Application_Start
実行されません。
図 4: ブレークポイントを使用してイベント ハンドラーが実行されていることを Application_Start
確認する (クリックするとフルサイズの画像が表示されます)
注意
最初にデバッグを開始するときにブレークポイントに Application_Start
ヒットしない場合は、アプリケーションが既に開始されているためです。 または Web.config
ファイルを変更してアプリケーションを強制的にGlobal.asax
再起動してから、もう一度やり直してください。 これらのファイルの末尾に空白行を追加 (または削除) するだけで、アプリケーションをすばやく再起動できます。
手順 5: キャッシュされたデータを表示する
この時点で、 StaticCache
クラスには、アプリケーションの起動時にキャッシュされたサプライヤー データのバージョンがあり、その GetSuppliers()
メソッドを介してアクセスできます。 プレゼンテーション レイヤーからこのデータを操作するには、ObjectDataSource を使用するか、ASP.NET ページの分離コード クラスからクラスの GetSuppliers()
メソッドをプログラムで呼び出すことができますStaticCache
。 ObjectDataSource コントロールと GridView コントロールを使用して、キャッシュされたサプライヤー情報を表示する方法を見てみましょう。
まず、フォルダー内の AtApplicationStartup.aspx
ページを Caching
開きます。 GridView をツールボックスからデザイナーにドラッグし、そのプロパティを ID
に Suppliers
設定します。 次に、GridView のスマート タグから、 という名前 SuppliersCachedDataSource
の新しい ObjectDataSource を作成することを選択します。 クラス s GetSuppliers()
メソッドを使用するように ObjectDataSource をStaticCache
構成します。
図 5: クラスを使用するように ObjectDataSource を構成する StaticCache
(フルサイズの画像を表示する をクリックします)
図 6: メソッドを GetSuppliers()
使用してキャッシュされた仕入先データを取得する (クリックするとフルサイズの画像が表示されます)
ウィザードが完了すると、Visual Studio によって、 の各データ フィールドに BoundFields が自動的に SuppliersDataTable
追加されます。 GridView と ObjectDataSource の宣言型マークアップは、次のようになります。
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersCachedDataSource"
EnableViewState="False">
<Columns>
<asp:BoundField DataField="SupplierID" HeaderText="SupplierID"
InsertVisible="False" ReadOnly="True"
SortExpression="SupplierID" />
<asp:BoundField DataField="CompanyName" HeaderText="CompanyName"
SortExpression="CompanyName" />
<asp:BoundField DataField="Address" HeaderText="Address"
SortExpression="Address" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
<asp:BoundField DataField="Phone" HeaderText="Phone"
SortExpression="Phone" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersCachedDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliers" TypeName="StaticCache" />
図 7 は、ブラウザーを介して表示されるページを示しています。 出力は、BLL s SuppliersBLL
クラスからデータをプルした場合と同じですが、 クラスを StaticCache
使用すると、アプリケーションの起動時にキャッシュされたサプライヤー データが返されます。 クラスの GetSuppliers()
メソッドにブレークポイントを設定して、StaticCache
この動作を確認できます。
図 7: キャッシュされたサプライヤー データが GridView に表示される (フルサイズの画像を表示する をクリックします)
まとめ
ほとんどのデータ モデルには、かなりの量の静的データが含まれています。通常は、参照テーブルの形式で実装されます。 この情報は静的であるため、この情報を表示する必要があるたびにデータベースに継続的にアクセスする理由はありません。 さらに、静的な性質により、データをキャッシュするときに有効期限が切れる必要はありません。 このチュートリアルでは、このようなデータを取得し、データ キャッシュ、アプリケーションの状態、および静的メンバー変数を使用してキャッシュする方法について説明しました。 この情報はアプリケーションの起動時にキャッシュされ、アプリケーションの有効期間中はキャッシュに残ります。
このチュートリアルと過去 2 回では、アプリケーションの有効期間の間のデータのキャッシュと、時間ベースの有効期限の使用について説明しました。 ただし、データベース データをキャッシュする場合、時間ベースの有効期限が理想的よりも短い場合があります。 キャッシュを定期的にフラッシュするのではなく、基になるデータベース データが変更された場合にのみ、キャッシュされた項目を削除するのが最適です。 この理想は、SQL キャッシュの依存関係を使用して可能です。これについては、次のチュートリアルで説明します。
幸せなプログラミング!
著者について
7 冊の ASP/ASP.NET 書籍の著者であり、 4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジと協力しています。 Scott は独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズ・ティーチ・自分自身 ASP.NET 24時間で2.0です。 にアクセスmitchell@4GuysFromRolla.comすることも、ブログを介して アクセスすることもできます。これは でhttp://ScottOnWriting.NET確認できます。
特別な感謝
このチュートリアル シリーズは、多くの役立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、テレサ マーフィーと Zack Jones でした。 今後の MSDN 記事の確認に関心がありますか? その場合は、 に行mitchell@4GuysFromRolla.comをドロップしてください。
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示