SQL 캐시 종속성 사용(C#)
작성자 : Scott Mitchell
가장 간단한 캐싱 전략은 캐시된 데이터가 지정된 기간 후에 만료되도록 하는 것입니다. 그러나 이 간단한 방법은 캐시된 데이터가 기본 데이터 원본과 아무런 관련이 없으므로 너무 오래 보유되거나 현재 데이터가 너무 빨리 만료되는 부실 데이터가 발생한다는 것을 의미합니다. SQL 데이터베이스에서 기본 데이터가 수정될 때까지 데이터가 캐시된 상태로 유지되도록 SqlCacheDependency 클래스를 사용하는 것이 더 좋습니다. 이 튜토리얼에서는 그 방법에 대해 설명합니다.
소개
아키텍처 자습서의 ObjectDataSource 및 캐싱 데이터를 사용하여 데이터 캐싱에서 검사한 캐싱 기술은 시간 기반 만료를 사용하여 지정된 기간 후에 캐시에서 데이터를 제거했습니다. 이 방법은 캐싱의 성능 향상과 데이터 부실의 균형을 맞추는 가장 간단한 방법입니다. 페이지 개발자는 x 초의 시간 만료를 선택하여 x 초 동안만 캐싱의 성능 이점을 누릴 수 있지만, 데이터가 최대 x 초보다 오래 부실하지 않도록 쉽게 휴식을 취합니다. 물론 정적 데이터의 경우 애플리케이션 시작에서 데이터 캐싱 자습서에서 검사한 대로 x를 웹 애플리케이션의 수명까지 확장할 수 있습니다.
데이터베이스 데이터를 캐싱할 때 사용 편의성을 위해 시간 기반 만료가 선택되는 경우가 많지만 종종 부적절한 솔루션입니다. 이상적으로 데이터베이스 데이터는 데이터베이스에서 기본 데이터가 수정될 때까지 캐시된 상태로 유지됩니다. 그러면 캐시가 제거됩니다. 이 방법은 캐싱의 성능 이점을 최대화하고 부실 데이터의 기간을 최소화합니다. 그러나 이러한 이점을 활용하려면 기본 데이터베이스 데이터가 수정된 시기를 알고 캐시에서 해당 항목을 제거할 수 있는 일부 시스템이 있어야 합니다. ASP.NET 2.0 이전에는 페이지 개발자가 이 시스템을 구현해야 했습니다.
ASP.NET 2.0은 해당 캐시된 항목을 제거할 수 있도록 데이터베이스에서 변경이 발생한 시기를 결정하는 데 필요한 클래스와 인프라를 제공합니다SqlCacheDependency
. 기본 데이터가 변경된 시기를 결정하는 방법에는 알림 및 폴링이라는 두 가지 기술이 있습니다. 알림과 폴링의 차이점을 논의한 후 폴링을 지원하는 데 필요한 인프라를 만든 다음 선언적 및 프로그래밍 방식으로 시나리오에서 클래스를 사용하는 SqlCacheDependency
방법을 살펴봅니다.
알림 및 폴링 이해
데이터베이스의 데이터가 수정된 시기를 확인하는 데 사용할 수 있는 두 가지 기술인 알림 및 폴링이 있습니다. 알림을 통해 데이터베이스는 쿼리가 마지막으로 실행된 이후 특정 쿼리의 결과가 변경된 경우 ASP.NET 런타임에 자동으로 경고합니다. 이때 쿼리와 연결된 캐시된 항목이 제거됩니다. 폴링을 사용하면 데이터베이스 서버는 특정 테이블이 마지막으로 업데이트된 시기에 대한 정보를 유지 관리합니다. ASP.NET 런타임은 데이터베이스를 주기적으로 폴링하여 캐시에 입력된 이후 변경된 테이블을 검사. 데이터가 수정된 테이블은 연결된 캐시 항목을 제거합니다.
알림 옵션은 폴링보다 덜 설정해야 하며 테이블 수준이 아닌 쿼리 수준에서 변경 내용을 추적하기 때문에 더 세분화됩니다. 아쉽게도 알림은 Microsoft SQL Server 2005(즉, Express가 아닌 버전)의 전체 버전에서만 사용할 수 있습니다. 그러나 폴링 옵션은 7.0에서 2005까지 모든 버전의 Microsoft SQL Server 사용할 수 있습니다. 이 자습서에서는 SQL Server 2005의 Express 버전을 사용하므로 폴링 옵션을 설정하고 사용하는 데 중점을 줍니다. SQL Server 2005 알림 기능에 대한 추가 리소스는 이 자습서의 끝에 있는 추가 읽기 섹션을 참조하세요.
폴링을 사용하면 , 및 changeId
열이 세 개 있는 라는 AspNet_SqlCacheTablesForChangeNotification
테이블을 포함하도록 데이터베이스를 tableName
notificationCreated
구성해야 합니다. 이 테이블에는 웹 애플리케이션의 SQL 캐시 종속성에서 사용해야 할 수 있는 데이터가 있는 각 테이블에 대한 행이 포함되어 있습니다. 열은 tableName
테이블의 이름을 지정하고 notificationCreated
행이 테이블에 추가된 날짜와 시간을 나타냅니다. 열은 changeId
형식 int
이며 초기 값은 0입니다. 테이블이 수정될 때마다 값이 증가합니다.
테이블 외에도 AspNet_SqlCacheTablesForChangeNotification
데이터베이스는 SQL 캐시 종속성에 나타날 수 있는 각 테이블에 트리거를 포함해야 합니다. 이러한 트리거는 행이 삽입, 업데이트 또는 삭제될 때마다 실행되며 에서 AspNet_SqlCacheTablesForChangeNotification
테이블 changeId
값을 증분합니다.
ASP.NET 런타임은 개체를 사용하여 SqlCacheDependency
데이터를 캐싱할 때 테이블의 현재 changeId
를 추적합니다. 데이터베이스가 주기적으로 검사되고 데이터베이스의 값과 다른 개체 SqlCacheDependency
changeId
는 데이터가 changeId
캐시된 이후 테이블이 변경되었음을 나타내므로 제거됩니다.
1단계: 명령줄 프로그램 탐색aspnet_regsql.exe
폴링 방법을 사용하면 미리 정의된 테이블(AspNet_SqlCacheTablesForChangeNotification
), 소수의 저장 프로시저 및 웹 애플리케이션의 SQL 캐시 종속성에서 사용할 수 있는 각 테이블에 대한 트리거와 같이 위에서 설명한 인프라를 포함하도록 데이터베이스를 설정해야 합니다. 이러한 테이블, 저장 프로시저 및 트리거는 폴더에 있는 $WINDOWS$\Microsoft.NET\Framework\version
명령줄 프로그램 aspnet_regsql.exe
를 통해 만들 수 있습니다. 테이블 및 연결된 저장 프로시저를 만들 AspNet_SqlCacheTablesForChangeNotification
려면 명령줄에서 다음을 실행합니다.
/* For SQL Server authentication... */
aspnet_regsql.exe -S server -U user -P password -d database -ed
/* For Windows Authentication... */
aspnet_regsql.exe -S server -E -d database -ed
참고
이러한 명령을 실행하려면 지정된 데이터베이스 로그인이 및 db_ddladmin
역할에 있어야 db_securityadmin
합니다.
예를 들어 Windows 인증을 사용하여 라는 데이터베이스 서버에서 라는 pubs
ScottsServer
Microsoft SQL Server 데이터베이스에 폴링을 위한 인프라를 추가하려면 적절한 디렉터리로 이동하고 명령줄에서 다음을 입력합니다.
aspnet_regsql.exe -S ScottsServer -E -d pubs -ed
데이터베이스 수준 인프라가 추가된 후 SQL 캐시 종속성에서 사용할 해당 테이블에 트리거를 추가해야 합니다. aspnet_regsql.exe
명령줄 프로그램을 다시 사용하지만 스위치를 사용하여 -t
테이블 이름을 지정하고 스위치를 사용하는 -ed
대신 다음과 같이 를 사용합니다-et
.
/* For SQL Server authentication... */
aspnet_regsql.exe -S <i>server</i>
-U <i>user</i> -P <i>password</i> -d <i>database</i> -t <i>tableName</i> -et
/* For Windows Authentication... */
aspnet_regsql.exe -S <i>server</i>
-E -d <i>database</i> -t <i>tableName</i> -et
에 있는 데이터베이스의 authors
및 titles
테이블에 트리거를 추가하려면 다음을 pubs
사용합니다.ScottsServer
aspnet_regsql.exe -S ScottsServer -E -d pubs -t authors -et
aspnet_regsql.exe -S ScottsServer -E -d pubs -t titles -et
이 자습서에서는 , Categories
및 Suppliers
테이블에 트리거를 Products
추가합니다. 3단계에서 특정 명령줄 구문을 살펴보겠습니다.
2단계: 에서 Microsoft SQL Server 2005 Express Edition 데이터베이스 참조App_Data
aspnet_regsql.exe
필요한 폴링 인프라를 추가하려면 명령줄 프로그램에 데이터베이스와 서버 이름이 필요합니다. 그러나 폴더에 있는 App_Data
Microsoft SQL Server 2005 Express 데이터베이스의 데이터베이스 및 서버 이름은 무엇인가요? 데이터베이스 및 서버 이름이 무엇인지 검색하는 대신 가장 간단한 방법은 데이터베이스 instance 데이터베이스에 localhost\SQLExpress
연결하고 SQL Server Management Studio 사용하여 데이터의 이름을 바꾸는 것입니다. 컴퓨터에 SQL Server 2005의 전체 버전 중 하나가 설치되어 있는 경우 컴퓨터에 이미 SQL Server Management Studio 설치되어 있을 수 있습니다. Express 버전만 있는 경우 무료 Microsoft SQL Server Management Studio Express Edition을 다운로드할 수 있습니다.
Visual Studio를 닫아 시작합니다. 다음으로, SQL Server Management Studio 열고 Windows 인증을 localhost\SQLExpress
사용하여 서버에 연결하도록 선택합니다.
그림 1: 서버에 연결 localhost\SQLExpress
서버에 연결한 후 Management Studio는 서버를 표시하고 데이터베이스, 보안 등에 대한 하위 폴더를 갖습니다. 데이터베이스 폴더를 마우스 오른쪽 단추로 클릭하고 연결 옵션을 선택합니다. 그러면 데이터베이스 연결 대화 상자가 표시됩니다(그림 2 참조). 추가 단추를 클릭하고 웹 애플리케이션의 폴더에서 데이터베이스 폴더를 App_Data
선택합니다NORTHWND.MDF
.
그림 2: 폴더에서 App_Data
데이터베이스 연결NORTHWND.MDF
(전체 크기 이미지를 보려면 클릭)
그러면 데이터베이스 폴더에 데이터베이스가 추가됩니다. 데이터베이스 이름은 데이터베이스 파일의 전체 경로이거나 GUID가 앞에 추가된 전체 경로일 수 있습니다. aspnet_regsql.exe 명령줄 도구를 사용할 때 이 긴 데이터베이스 이름을 입력할 필요가 없도록 하려면 방금 연결된 데이터베이스를 마우스 오른쪽 단추로 클릭하고 이름 바꾸기를 선택하여 데이터베이스 이름을 보다 친숙한 이름으로 바꿉니다. 데이터베이스 이름을 DataTutorials 로 변경했습니다.
그림 3: 연결된 데이터베이스의 이름을 더 Human-Friendly 이름으로 바꿉니다.
3단계: Northwind 데이터베이스에 폴링 인프라 추가
이제 폴더에서 데이터베이스를 NORTHWND.MDF
App_Data
연결했으므로 폴링 인프라를 추가할 준비가 되었습니다. 데이터베이스 이름을 DataTutorials로 변경한 경우 다음 네 가지 명령을 실행합니다.
aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -ed
aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -t Products -et
aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -t Categories -et
aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -t Suppliers -et
이러한 네 가지 명령을 실행한 후 Management Studio에서 데이터베이스 이름을 마우스 오른쪽 단추로 클릭하고 작업 하위 메뉴로 이동하여 분리를 선택합니다. 그런 다음, Management Studio를 닫고 Visual Studio를 다시 엽니다.
Visual Studio가 다시 열리면 서버 Explorer 통해 데이터베이스를 드릴합니다. 새 테이블(AspNet_SqlCacheTablesForChangeNotification
), 새 저장 프로시저 및 , Categories
및 Suppliers
테이블의 트리거를 Products
확인합니다.
그림 4: 이제 데이터베이스에 필요한 폴링 인프라가 포함됨
4단계: 폴링 서비스 구성
데이터베이스에서 필요한 테이블, 트리거 및 저장 프로시저를 만든 후 마지막 단계는 사용할 데이터베이스와 폴링 빈도(밀리초)를 지정하여 수행 Web.config
되는 폴링 서비스를 구성하는 것입니다. 다음 태그는 1초에 한 번씩 Northwind 데이터베이스를 폴링합니다.
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="NORTHWNDConnectionString" connectionString=
"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\NORTHWND.MDF;
Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient"/>
</connectionStrings>
<system.web>
...
<!-- Configure the polling service used for SQL cache dependencies -->
<caching>
<sqlCacheDependency enabled="true" pollTime="1000" >
<databases>
<add name="NorthwindDB"
connectionStringName="NORTHWNDConnectionString" />
</databases>
</sqlCacheDependency>
</caching>
</system.web>
</configuration>
요소(NorthwindDB)의 <add>
값은 name
사람이 읽을 수 있는 이름을 특정 데이터베이스와 연결합니다. SQL 캐시 종속성을 사용하는 경우 여기에 정의된 데이터베이스 이름과 캐시된 데이터의 기반이 되는 테이블을 참조해야 합니다. 클래스를 사용하여 SqlCacheDependency
6단계에서 SQL 캐시 종속성을 캐시된 데이터와 프로그래밍 방식으로 연결하는 방법을 알아봅니다.
SQL 캐시 종속성이 설정되면 폴링 시스템은 밀리초마다 pollTime
요소에 정의된 데이터베이스에 <databases>
연결하고 저장 프로시저를 AspNet_SqlCachePollingStoredProcedure
실행합니다. 명령줄 도구를 사용하여 aspnet_regsql.exe
3단계에서 다시 추가된 이 저장 프로시저는 의 AspNet_SqlCacheTablesForChangeNotification
각 레코드에 대한 및 changeId
값을 반환합니다tableName
. 오래된 SQL 캐시 종속성은 캐시에서 제거됩니다.
이 설정은 pollTime
성능과 데이터 부실 간의 절충을 도입합니다. 값이 작 pollTime
을수록 데이터베이스에 대한 요청 수가 증가하지만 캐시에서 오래된 데이터가 더 빠르게 제거됩니다. 값이 클 pollTime
수록 데이터베이스 요청 수가 줄어들지만 백 엔드 데이터가 변경되는 시기와 관련 캐시 항목이 제거되는 시점 사이의 지연이 증가합니다. 다행히 데이터베이스 요청은 간단한 간단한 테이블에서 몇 개의 행만 반환하는 간단한 저장 프로시저를 실행합니다. 그러나 다른 pollTime
값을 실험하여 애플리케이션에 대한 데이터베이스 액세스와 데이터 부실 간의 이상적인 균형을 찾습니다. 허용되는 가장 pollTime
작은 값은 500입니다.
참고
위의 예제에서는 요소에 <sqlCacheDependency>
단일 pollTime
값을 제공하지만 필요에 따라 요소의 pollTime
<add>
값을 지정할 수 있습니다. 이 기능은 여러 데이터베이스를 지정하고 데이터베이스당 폴링 빈도를 사용자 지정하려는 경우에 유용합니다.
5단계: 선언적으로 SQL 캐시 종속성 작업
1~4단계에서는 필요한 데이터베이스 인프라를 설치하고 폴링 시스템을 구성하는 방법을 살펴보았습니다. 이 인프라를 사용하면 이제 프로그래밍 방식 또는 선언적 기술을 사용하여 연결된 SQL 캐시 종속성을 사용하여 데이터 캐시에 항목을 추가할 수 있습니다. 이 단계에서는 SQL 캐시 종속성을 선언적으로 사용하는 방법을 살펴보겠습니다. 6단계에서는 프로그래밍 방식 방식을 살펴보겠습니다.
ObjectDataSource를 사용하여 데이터 캐싱 자습서에서는 ObjectDataSource의 선언적 캐싱 기능을 살펴보했습니다. 속성을 로 설정하고 CacheDuration
속성을 true
일정 시간 간격으로 설정 EnableCaching
하면 ObjectDataSource는 지정된 간격 동안 기본 개체에서 반환된 데이터를 자동으로 캐시합니다. ObjectDataSource는 하나 이상의 SQL 캐시 종속성을 사용할 수도 있습니다.
SQL 캐시 종속성을 선언적으로 사용하는 방법을 보여 주려면 폴더에서 페이지를 열고 SqlCacheDependencies.aspx
Toolbox에서 Caching
Designer GridView를 끌어옵니다. GridView를 ID
로 ProductsDeclarative
설정하고 스마트 태그에서 라는 새 ObjectDataSource ProductsDataSourceDeclarative
에 바인딩하도록 선택합니다.
그림 5: 새 ObjectDataSource 명명된 ProductsDataSourceDeclarative
만들기(전체 크기 이미지를 보려면 클릭)
클래스를 사용하도록 ObjectDataSource를 ProductsBLL
구성하고 SELECT 탭의 드롭다운 목록을 로 GetProducts()
설정합니다. UPDATE 탭에서 세 개의 입력 매개 변수productName
인 UpdateProduct
, unitPrice
및 를 사용하여 오버로드를 productID
선택합니다. 삽입 및 삭제 탭에서 드롭다운 목록을 (없음)으로 설정합니다.
그림 6: 세 개의 입력 매개 변수와 함께 UpdateProduct 오버로드 사용(전체 크기 이미지를 보려면 클릭)
그림 7: INSERT 및 DELETE 탭의 Drop-Down 목록을 (없음)으로 설정합니다(전체 크기 이미지를 보려면 클릭).
데이터 원본 구성 마법사를 완료한 후 Visual Studio는 각 데이터 필드에 대한 GridView에 BoundFields 및 CheckBoxFields를 만듭니다. , CategoryName
및 UnitPrice
을 제외한 ProductName
모든 필드를 제거하고 이러한 필드의 서식을 적합하게 표시합니다. GridView의 스마트 태그에서 페이징 사용, 정렬 사용 및 편집 사용 확인란을 검사. Visual Studio는 ObjectDataSource의 OldValuesParameterFormatString
속성을 로 original_{0}
설정합니다. GridView의 편집 기능이 제대로 작동하려면 선언적 구문에서 이 속성을 완전히 제거하거나 기본값 {0}
으로 다시 설정합니다.
마지막으로 GridView 위에 레이블 웹 컨트롤을 추가하고 속성을 로 설정하고 해당 ID
EnableViewState
속성을 ODSEvents
로 false
설정합니다. 이러한 변경을 수행한 후 페이지의 선언적 태그는 다음과 유사하게 표시됩니다. SQL 캐시 종속성 기능을 보여 줄 필요가 없는 GridView 필드에 대해 여러 가지 미적 사용자 지정을 수행했습니다.
<asp:Label ID="ODSEvents" runat="server" EnableViewState="False" />
<asp:GridView ID="ProductsDeclarative" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsDataSourceDeclarative"
AllowPaging="True" AllowSorting="True">
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:TemplateField HeaderText="Product" SortExpression="ProductName">
<EditItemTemplate>
<asp:TextBox ID="ProductName" runat="server"
Text='<%# Bind("ProductName") %>' />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
ControlToValidate="ProductName" Display="Dynamic"
ErrorMessage="You must provide a name for the product."
SetFocusOnError="True"
runat="server">*</asp:RequiredFieldValidator>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server"
Text='<%# Bind("ProductName") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="CategoryName" HeaderText="Category"
ReadOnly="True" SortExpression="CategoryName" />
<asp:TemplateField HeaderText="Price" SortExpression="UnitPrice">
<EditItemTemplate>
$<asp:TextBox ID="UnitPrice" runat="server" Columns="8"
Text='<%# Bind("UnitPrice", "{0:N2}") %>'></asp:TextBox>
<asp:CompareValidator ID="CompareValidator1" runat="server"
ControlToValidate="UnitPrice"
ErrorMessage="You must enter a valid currency value with
no currency symbols. Also, the value must be greater than
or equal to zero."
Operator="GreaterThanEqual" SetFocusOnError="True"
Type="Currency" Display="Dynamic"
ValueToCompare="0">*</asp:CompareValidator>
</EditItemTemplate>
<ItemStyle HorizontalAlign="Right" />
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Text='<%# Bind("UnitPrice", "{0:c}") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSourceDeclarative" runat="server"
SelectMethod="GetProducts" TypeName="ProductsBLL"
UpdateMethod="UpdateProduct">
<UpdateParameters>
<asp:Parameter Name="productName" Type="String" />
<asp:Parameter Name="unitPrice" Type="Decimal" />
<asp:Parameter Name="productID" Type="Int32" />
</UpdateParameters>
</asp:ObjectDataSource>
다음으로 ObjectDataSource 이벤트에 Selecting
대한 이벤트 처리기를 만들고 여기에 다음 코드를 추가합니다.
protected void ProductsDataSourceDeclarative_Selecting
(object sender, ObjectDataSourceSelectingEventArgs e)
{
ODSEvents.Text = "-- Selecting event fired";
}
ObjectDataSource의 Selecting
이벤트는 기본 개체에서 데이터를 검색할 때만 발생합니다. ObjectDataSource가 자체 캐시에서 데이터에 액세스하는 경우 이 이벤트가 발생하지 않습니다.
이제 브라우저를 통해 이 페이지를 방문하세요. 아직 캐싱을 구현하지 않았으므로 페이지, 정렬 또는 편집할 때마다 페이지에 그림 8과 같이 '발생한 이벤트 선택' 텍스트가 표시됩니다.
그림 8: GridView가 페이징, 편집 또는 정렬될 때마다 ObjectDataSource 이벤트가 Selecting
발생합니다(전체 크기 이미지를 보려면 클릭).
ObjectDataSource를 사용하여 데이터 캐싱 자습서에서 확인한 것처럼 속성을 true
로 설정 EnableCaching
하면 ObjectDataSource가 해당 속성에 CacheDuration
지정된 기간 동안 해당 데이터를 캐시합니다. ObjectDataSource에는 SqlCacheDependency
패턴을 사용하여 캐시된 데이터에 하나 이상의 SQL 캐시 종속성을 추가하는 속성도 있습니다.
databaseName1:tableName1;databaseName2:tableName2;...
여기서 databaseName은 에 있는 요소Web.config
의 특성에 name
지정된 대로 데이터베이스의 <add>
이름이고 tableName은 데이터베이스 테이블의 이름입니다. 예를 들어 Northwind 테이블에 대한 SQL 캐시 종속성을 기반으로 데이터를 무기한 캐시하는 ObjectDataSource를 만들려면 ObjectDataSource의 Products
EnableCaching
속성을 로 설정하고 해당 SqlCacheDependency
속성을 true
NorthwindDB:Products 로 설정합니다.
참고
을 시간 간격으로, 데이터베이스 및 테이블 이름으로 설정 EnableCaching
true
CacheDuration
하여 SQL 캐시 종속성 및 SqlCacheDependency
시간 기반 만료를 사용할 수 있습니다. ObjectDataSource는 시간 기반 만료에 도달하거나 폴링 시스템에서 기본 데이터베이스 데이터가 변경되었음을 기록할 때 데이터를 제거합니다. 어느 것이든 먼저 발생합니다.
의 SqlCacheDependencies.aspx
GridView는 및 두 테이블 Products
의 CategoryName
데이터를 표시합니다 Categories
(제품의 필드는 의 Categories
를 JOIN
통해 검색됨). 따라서 NorthwindDB:Products라는 두 개의 SQL 캐시 종속성을 지정하려고 합니다. NorthwindDB:Categories .
그림 9: 및 에서 SQL 캐시 종속성을 Products
Categories
사용하여 캐싱을 지원하도록 ObjectDataSource 구성(전체 크기 이미지를 보려면 클릭)
캐싱을 지원하도록 ObjectDataSource를 구성한 후 브라우저를 통해 페이지를 다시 방문합니다. 다시 말하지만 '이벤트 선택 발생'은 첫 번째 페이지 방문에 나타나야 하지만 편집 또는 취소 단추를 페이징, 정렬 또는 클릭할 때는 사라집니다. 이는 데이터가 ObjectDataSource의 캐시에 로드된 후 또는 Categories
테이블이 수정되거나 GridView를 통해 데이터가 업데이트될 때까지 Products
데이터가 유지되기 때문입니다.
그리드를 페이징하고 '이벤트 실행된 텍스트 선택'이 없음을 표시한 후 새 브라우저 창을 열고 편집, 삽입 및 삭제 섹션()의 기본 사항 자습서로~/EditInsertDelete/Basics.aspx
이동합니다. 제품의 이름 또는 가격을 업데이트합니다. 그런 다음 첫 번째 브라우저 창에서 다른 데이터 페이지를 보거나 그리드를 정렬하거나 행의 편집 단추를 클릭합니다. 이번에는 기본 데이터베이스 데이터가 수정되었으므로 '발생한 선택 이벤트가 다시 나타납니다(그림 10 참조). 텍스트가 표시되지 않으면 잠시 기다렸다가 다시 시도합니다. 폴링 서비스는 매 밀리초마다 pollTime
테이블의 변경 내용을 Products
확인하므로 기본 데이터가 업데이트되는 시기와 캐시된 데이터가 제거되는 시점 사이에 지연이 발생합니다.
그림 10: 제품 테이블을 수정하면 캐시된 제품 데이터가 제거됩니다(전체 크기 이미지를 보려면 클릭).
6단계: 프로그래밍 방식으로 클래스 작업SqlCacheDependency
아키텍처의 캐싱 데이터 자습서에서는 캐싱을 ObjectDataSource와 긴밀하게 결합하는 대신 아키텍처에서 별도의 캐싱 계층을 사용하는 이점을 살펴보았습니다. 이 자습서에서는 프로그래밍 방식으로 데이터 캐시를 사용하는 방법을 보여 주는 클래스를 만들었습니다 ProductsCL
. 캐싱 계층에서 SQL 캐시 종속성을 활용하려면 클래스를 SqlCacheDependency
사용합니다.
폴링 시스템을 사용하면 개체를 SqlCacheDependency
특정 데이터베이스 및 테이블 쌍과 연결해야 합니다. 예를 들어 다음 코드는 Northwind 데이터베이스의 Products
테이블을 기반으로 개체를 만듭니다SqlCacheDependency
.
Caching.SqlCacheDependency productsTableDependency =
new Caching.SqlCacheDependency("NorthwindDB", "Products");
생성자에 대한 SqlCacheDependency
두 개의 입력 매개 변수는 각각 데이터베이스 및 테이블 이름입니다. ObjectDataSource의 SqlCacheDependency
속성과 마찬가지로 사용되는 데이터베이스 이름은 에 있는 요소Web.config
의 특성에 name
지정된 값과 <add>
동일합니다. 테이블 이름은 데이터베이스 테이블의 실제 이름입니다.
를 데이터 캐시에 추가된 항목과 연결 SqlCacheDependency
하려면 종속성을 허용하는 메서드 오버로드 중 Insert
하나를 사용합니다. 다음 코드는 무기한 동안 데이터 캐시에 값을 추가하지만 테이블의 Products
에 SqlCacheDependency
연결합니다. 즉, 메모리 제약 조건으로 인해 제거되거나 폴링 시스템에서 테이블이 캐시된 이후 변경되었음을 감지했기 때문에 값 은 캐시에 Products
유지됩니다.
Caching.SqlCacheDependency productsTableDependency =
new Caching.SqlCacheDependency("NorthwindDB", "Products");
Cache.Insert(key,
value,
productsTableDependency,
System.Web.Caching.Cache.NoAbsoluteExpiration,
System.Web.Caching.Cache.NoSlidingExpiration);
캐싱 계층의 ProductsCL
클래스는 현재 60초의 시간 기반 만료를 사용하여 테이블의 데이터를 Products
캐시합니다. SQL 캐시 종속성을 대신 사용할 수 있도록 이 클래스를 업데이트해 보겠습니다. ProductsCL
캐시에 데이터를 추가하는 클래스의 AddCacheItem
메서드는 현재 다음 코드를 포함합니다.
private void AddCacheItem(string rawKey, object value)
{
System.Web.Caching.Cache DataCache = HttpRuntime.Cache;
// Make sure MasterCacheKeyArray[0] is in the cache
DataCache[MasterCacheKeyArray[0]] = DateTime.Now;
// Add a CacheDependency
Caching.CacheDependency dependency =
new Caching.CacheDependency(null, MasterCacheKeyArray);
DataCache.Insert(GetCacheKey(rawKey), value, dependency,
DateTime.Now.AddSeconds(CacheDuration),
System.Web.Caching.Cache.NoSlidingExpiration);
}
캐시 종속성 대신 MasterCacheKeyArray
개체를 SqlCacheDependency
사용하도록 이 코드를 업데이트합니다.
private void AddCacheItem(string rawKey, object value)
{
System.Web.Caching.Cache DataCache = HttpRuntime.Cache;
// Add the SqlCacheDependency objects for Products
Caching.SqlCacheDependency productsTableDependency =
new Caching.SqlCacheDependency("NorthwindDB", "Products");
// Add the item to the data cache using productsTableDependency
DataCache.Insert(GetCacheKey(rawKey), value, productsTableDependency,
Caching.Cache.NoAbsoluteExpiration, Caching.Cache.NoSlidingExpiration);
}
이 기능을 테스트하려면 기존 GridView 아래의 페이지에 GridView를 ProductsDeclarative
추가합니다. 이 새 GridView를 ID
ProductsProgrammatic
로 설정하고 스마트 태그를 통해 라는 새 ObjectDataSource ProductsDataSourceProgrammatic
에 바인딩합니다. 클래스를 사용하도록 ObjectDataSource를 ProductsCL
구성하고 SELECT 및 UPDATE 탭의 드롭다운 목록을 각각 및 UpdateProduct
로 GetProducts
설정합니다.
그림 11: 클래스를 사용하도록 ProductsCL
ObjectDataSource 구성(전체 크기 이미지를 보려면 클릭)
그림 12: SELECT Tab의 Drop-Down 목록에서 메서드를 선택합니다 GetProducts
(전체 크기 이미지를 보려면 클릭).
그림 13: 업데이트 탭의 Drop-Down 목록에서 UpdateProduct 메서드 선택(전체 크기 이미지를 보려면 클릭)
데이터 원본 구성 마법사를 완료한 후 Visual Studio는 각 데이터 필드에 대한 GridView에 BoundFields 및 CheckBoxFields를 만듭니다. 이 페이지에 추가된 첫 번째 GridView와 마찬가지로 , CategoryName
및 UnitPrice
을 제외한 ProductName
모든 필드를 제거하고 원하는 대로 이러한 필드의 서식을 지정합니다. GridView의 스마트 태그에서 페이징 사용, 정렬 사용 및 편집 사용 확인란을 검사. ObjectDataSource와 ProductsDataSourceDeclarative
마찬가지로 Visual Studio는 ObjectDataSource의 OldValuesParameterFormatString
속성을 로 original_{0}
설정합니다ProductsDataSourceProgrammatic
. GridView의 편집 기능이 제대로 작동하려면 이 속성을 로 다시 {0}
설정하거나 선언적 구문에서 속성 할당을 모두 제거합니다.
이러한 작업을 완료한 후 결과 GridView 및 ObjectDataSource 선언적 태그는 다음과 같이 표시됩니다.
<asp:GridView ID="ProductsProgrammatic" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsDataSourceProgrammatic" AllowPaging="True"
AllowSorting="True">
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:TemplateField HeaderText="Product" SortExpression="ProductName">
<EditItemTemplate>
<asp:TextBox ID="ProductName" runat="server"
Text='<%# Bind("ProductName") %>' />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
ControlToValidate="ProductName" Display="Dynamic"
ErrorMessage="You must provide a name for the product."
SetFocusOnError="True"
runat="server">*</asp:RequiredFieldValidator>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server"
Text='<%# Bind("ProductName") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="CategoryName" HeaderText="Category"
ReadOnly="True" SortExpression="CategoryName" />
<asp:TemplateField HeaderText="Price" SortExpression="UnitPrice">
<EditItemTemplate>
$<asp:TextBox ID="UnitPrice" runat="server" Columns="8"
Text='<%# Bind("UnitPrice", "{0:N2}") %>'></asp:TextBox>
<asp:CompareValidator ID="CompareValidator1" runat="server"
ControlToValidate="UnitPrice" Display="Dynamic"
ErrorMessage="You must enter a valid currency value with
no currency symbols. Also, the value must be greater than
or equal to zero."
Operator="GreaterThanEqual" SetFocusOnError="True"
Type="Currency" ValueToCompare="0">*</asp:CompareValidator>
</EditItemTemplate>
<ItemStyle HorizontalAlign="Right" />
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Text='<%# Bind("UnitPrice", "{0:c}") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSourceProgrammatic" runat="server"
OldValuesParameterFormatString="{0}" SelectMethod="GetProducts"
TypeName="ProductsCL" UpdateMethod="UpdateProduct">
<UpdateParameters>
<asp:Parameter Name="productName" Type="String" />
<asp:Parameter Name="unitPrice" Type="Decimal" />
<asp:Parameter Name="productID" Type="Int32" />
</UpdateParameters>
</asp:ObjectDataSource>
캐싱 계층에서 SQL 캐시 종속성을 테스트하려면 클래스의 AddCacheItem
메서드에서 ProductCL
중단점을 설정한 다음 디버깅을 시작합니다. 를 처음 방문할 SqlCacheDependencies.aspx
때 데이터가 처음으로 요청되고 캐시에 배치될 때 중단점이 적중되어야 합니다. 다음으로 GridView의 다른 페이지로 이동하거나 열 중 하나를 정렬합니다. 이로 인해 GridView는 해당 데이터를 다시 쿼리하지만 데이터베이스 테이블이 수정되지 않았으므로 캐시 Products
에서 데이터를 찾아야 합니다. 캐시에서 데이터를 반복적으로 찾을 수 없는 경우 컴퓨터에서 사용 가능한 메모리가 충분한지 확인하고 다시 시도하세요.
GridView의 몇 페이지를 페이징한 후 두 번째 브라우저 창을 열고 편집, 삽입 및 삭제 섹션()의 기본 사항 자습서로~/EditInsertDelete/Basics.aspx
이동합니다. Products 테이블에서 레코드를 업데이트한 다음, 첫 번째 브라우저 창에서 새 페이지를 보거나 정렬 헤더 중 하나를 클릭합니다.
이 시나리오에서는 중단점이 적중되고 데이터베이스 변경으로 인해 캐시된 데이터가 제거되었음을 나타내는 두 가지 중 하나가 표시됩니다. 또는 중단점이 적중되지 않습니다. 즉 SqlCacheDependencies.aspx
, 현재 부실 데이터를 표시합니다. 중단점에 도달하지 않으면 데이터가 변경된 이후 폴링 서비스가 아직 실행되지 않았기 때문일 수 있습니다. 폴링 서비스는 1밀리초마다 pollTime
테이블의 변경 내용을 Products
확인하므로 기본 데이터가 업데이트되는 시기와 캐시된 데이터가 제거되는 시점 사이에 지연이 있습니다.
참고
이 지연은 의 GridView SqlCacheDependencies.aspx
를 통해 제품 중 하나를 편집할 때 나타날 가능성이 높습니다. 아키텍처 자습서의 데이터 캐싱 자습서에서는 클래스의 UpdateProduct
메서드를 통해 ProductsCL
편집되는 데이터가 캐시에서 제거되도록 캐시 종속성을 추가 MasterCacheKeyArray
했습니다. 그러나 이 단계의 앞부분에서 메서드를 수정할 AddCacheItem
때 이 캐시 종속성을 대체했으므로 ProductsCL
폴링 시스템이 테이블에 변경 내용을 표시할 때까지 클래스는 캐시된 데이터를 계속 표시합니다 Products
. 7단계에서 캐시 종속성을 다시 도입하는 MasterCacheKeyArray
방법을 살펴보겠습니다.
7단계: 여러 종속성을 캐시된 항목과 연결
MasterCacheKeyArray
캐시 종속성은 캐시 내에 연결된 단일 항목이 업데이트될 때 모든 제품 관련 데이터가 캐시에서 제거되도록 하는 데 사용됩니다. 예를 들어 메서드는 GetProductsByCategoryID(categoryID)
각 고유한 categoryID 값에 대한 인스턴스를 캐시 ProductsDataTables
합니다. 이러한 개체 중 하나가 제거되면 MasterCacheKeyArray
캐시 종속성으로 다른 개체도 제거됩니다. 이 캐시 종속성이 없으면 캐시된 데이터가 수정될 때 다른 캐시된 제품 데이터가 만료될 가능성이 있습니다. 따라서 SQL 캐시 종속성을 사용할 때 캐시 종속성을 유지하는 MasterCacheKeyArray
것이 중요합니다. 그러나 데이터 캐시의 Insert
메서드는 단일 종속성 개체만 허용합니다.
또한 SQL 캐시 종속성을 사용하는 경우 여러 데이터베이스 테이블을 종속성으로 연결해야 할 수 있습니다. 예를 들어 ProductsDataTable
클래스에 ProductsCL
캐시된 는 각 제품에 대한 범주 및 공급자 이름을 포함하지만 메서드는 AddCacheItem
에 대한 Products
종속성만 사용합니다. 이 경우 사용자가 범주 또는 공급자의 이름을 업데이트하는 경우 캐시된 제품 데이터는 캐시에 남아 있으며 최신이 아닙니다. 따라서 캐시된 제품 데이터는 테이블뿐만 Products
아니라 및 Suppliers
테이블에 Categories
도 종속되도록 하고자 합니다.
클래스는 AggregateCacheDependency
여러 종속성을 캐시 항목과 연결하기 위한 수단을 제공합니다. 먼저 instance 만듭니다 AggregateCacheDependency
. 다음으로, s Add
메서드를 사용하여 종속성 집합을 AggregateCacheDependency
추가합니다. 그 후 데이터 캐시에 항목을 삽입할 때 instance 전달 AggregateCacheDependency
합니다. AggregateCacheDependency
instance 종속성이 변경되면 캐시된 항목이 제거됩니다.
다음은 클래스의 AddCacheItem
메서드에 대한 업데이트된 ProductsCL
코드를 보여줍니다. 메서드는 , 및 테이블에 대한 Products
개체와 SqlCacheDependency
함께 캐시 종속성을 만듭니다MasterCacheKeyArray
.Suppliers
Categories
이러한 개체는 모두 라는 aggregateDependencies
하나의 AggregateCacheDependency
개체로 결합된 다음 메서드에 Insert
전달됩니다.
private void AddCacheItem(string rawKey, object value)
{
System.Web.Caching.Cache DataCache = HttpRuntime.Cache;
// Make sure MasterCacheKeyArray[0] is in the cache and create a depedency
DataCache[MasterCacheKeyArray[0]] = DateTime.Now;
Caching.CacheDependency masterCacheKeyDependency =
new Caching.CacheDependency(null, MasterCacheKeyArray);
// Add the SqlCacheDependency objects for Products, Categories, and Suppliers
Caching.SqlCacheDependency productsTableDependency =
new Caching.SqlCacheDependency("NorthwindDB", "Products");
Caching.SqlCacheDependency categoriesTableDependency =
new Caching.SqlCacheDependency("NorthwindDB", "Categories");
Caching.SqlCacheDependency suppliersTableDependency =
new Caching.SqlCacheDependency("NorthwindDB", "Suppliers");
// Create an AggregateCacheDependency
Caching.AggregateCacheDependency aggregateDependencies =
new Caching.AggregateCacheDependency();
aggregateDependencies.Add(masterCacheKeyDependency, productsTableDependency,
categoriesTableDependency, suppliersTableDependency);
DataCache.Insert(GetCacheKey(rawKey), value, aggregateDependencies,
Caching.Cache.NoAbsoluteExpiration, Caching.Cache.NoSlidingExpiration);
}
이 새 코드를 테스트합니다. 이제 , Categories
또는 Suppliers
테이블이 Products
변경되면 캐시된 데이터가 제거됩니다. 또한 ProductsCL
GridView를 통해 제품을 편집할 때 호출되는 클래스의 UpdateProduct
메서드는 캐시 종속성을 제거 MasterCacheKeyArray
하므로 캐시 ProductsDataTable
가 제거되고 다음 요청에서 데이터가 다시 검색됩니다.
참고
SQL 캐시 종속성을 출력 캐싱과 함께 사용할 수도 있습니다. 이 기능에 대한 데모는 SQL Server ASP.NET 출력 캐싱 사용을 참조하세요.
요약
데이터베이스 데이터를 캐싱할 때 데이터는 데이터베이스에서 수정될 때까지 캐시에 유지되는 것이 가장 좋습니다. ASP.NET 2.0을 사용하면 선언적 시나리오와 프로그래밍 방식 시나리오 모두에서 SQL 캐시 종속성을 만들고 사용할 수 있습니다. 이 방법의 과제 중 하나는 데이터가 수정된 시기를 검색하는 것입니다. Microsoft SQL Server 2005의 전체 버전은 쿼리 결과가 변경되면 애플리케이션에 경고할 수 있는 알림 기능을 제공합니다. SQL Server 2005 및 이전 버전의 SQL Server Express 버전의 경우 폴링 시스템을 대신 사용해야 합니다. 다행히 필요한 폴링 인프라를 설정하는 것은 매우 간단합니다.
행복한 프로그래밍!
추가 정보
이 자습서에서 설명하는 topics 대한 자세한 내용은 다음 리소스를 참조하세요.
- Microsoft SQL Server 2005에서 쿼리 알림 사용
- 쿼리 알림 만들기
- 클래스를 사용하여 ASP.NET
SqlCacheDependency
캐싱 - ASP.NET SQL Server 등록 도구(
aspnet_regsql.exe
) - 개요
SqlCacheDependency
저자 정보
7개의 ASP/ASP.NET 책의 저자이자 4GuysFromRolla.com 창립자인 Scott Mitchell은 1998년부터 Microsoft 웹 기술로 작업해 왔습니다. Scott은 독립 컨설턴트, 트레이너 및 작가로 일합니다. 그의 최신 책은 샘스 티치 유어셀프 ASP.NET 24시간 만에 2.0입니다. 그는 에서mitchell@4GuysFromRolla.com 또는 에서 찾을 http://ScottOnWriting.NET수있는 자신의 블로그를 통해 도달 할 수 있습니다.
특별 감사
이 자습서 시리즈는 많은 유용한 검토자가 검토했습니다. 이 자습서의 수석 검토자는 마르코 레인젤, 테레사 머피, 힐튼 기제나우였습니다. 예정된 MSDN 문서를 검토하는 데 관심이 있으신가요? 그렇다면 에 줄을 놓습니다 mitchell@4GuysFromRolla.com.