아키텍처에서 데이터 캐싱(VB)

작성자 : Scott Mitchell

PDF 다운로드

이전 자습서에서는 프레젠테이션 계층에서 캐싱을 적용하는 방법을 알아보았습니다. 이 자습서에서는 계층화된 아키텍처를 활용하여 비즈니스 논리 계층에서 데이터를 캐시하는 방법을 알아봅니다. 이 작업은 캐싱 계층을 포함하도록 아키텍처를 확장하여 수행합니다.

소개

앞의 자습서에서 볼 수 있듯이 ObjectDataSource의 데이터를 캐싱하는 것은 몇 가지 속성을 설정하는 것만큼 간단합니다. 아쉽게도 ObjectDataSource는 프레젠테이션 계층에 캐싱을 적용하여 캐싱 정책을 ASP.NET 페이지와 긴밀하게 결합합니다. 계층화된 아키텍처를 만드는 이유 중 하나는 이러한 결합을 끊을 수 있기 때문입니다. instance 비즈니스 논리 계층은 ASP.NET 페이지에서 비즈니스 논리를 분리하고 데이터 액세스 계층은 데이터 액세스 세부 정보를 분리합니다. 비즈니스 논리 및 데이터 액세스 세부 정보의 이러한 분리는 시스템을 더 읽기 능률적이고 유지 관리가 가능하며 변경하기 유연하게 만들기 때문에 부분적으로 선호됩니다. 또한 프레젠테이션 계층에서 작업하는 개발자가 작업을 수행하기 위해 데이터베이스의 세부 정보를 잘 알고 있을 필요가 없는 도메인 지식 및 노동 분할을 허용합니다. 프레젠테이션 계층에서 캐싱 정책을 분리하면 비슷한 이점이 있습니다.

이 자습서에서는 캐싱 정책을 사용하는 캐싱 계층 (또는 짧은 CL)을 포함하도록 아키텍처를 보강합니다. 캐싱 계층에는 , GetProductsByCategoryID(categoryID)등과 같은 GetProducts()메서드를 사용하여 제품 정보에 대한 액세스를 제공하는 클래스가 포함 ProductsCL 됩니다. 이 클래스는 호출될 때 먼저 캐시에서 데이터를 검색하려고 시도합니다. 캐시가 비어 있으면 이러한 메서드는 BLL에서 적절한 ProductsBLL 메서드를 호출합니다. 그러면 DAL에서 데이터를 가져옵니다. 메서드는 ProductsCL BLL에서 검색된 데이터를 반환하기 전에 캐시합니다.

그림 1에서 보여 주듯이 CL은 프레젠테이션과 비즈니스 논리 계층 사이에 있습니다.

CL(캐싱 계층)은 아키텍처의 또 다른 계층입니다.

그림 1: CL(캐싱 계층)은 아키텍처의 또 다른 계층입니다.

1단계: 캐싱 계층 클래스 만들기

이 자습서에서는 소수의 메서드만 있는 단일 클래스 ProductsCL 를 사용하여 매우 간단한 CL을 만듭니다. 전체 애플리케이션에 대한 전체 캐싱 계층을 빌드하려면 , EmployeesCLSuppliersCL 클래스를 만들고 CategoriesCLBLL의 각 데이터 액세스 또는 수정 메서드에 대해 이러한 캐싱 계층 클래스에 메서드를 제공해야 합니다. BLL 및 DAL과 마찬가지로 캐싱 계층은 별도의 클래스 라이브러리 프로젝트로 구현하는 것이 이상적입니다. 그러나 폴더에서 App_Code 클래스로 구현합니다.

CL 클래스를 DAL 및 BLL 클래스와 보다 명확하게 분리하려면 폴더에 새 하위 폴더를 App_Code 만들어 보겠습니다. 솔루션 탐색기 폴더를 App_Code 마우스 오른쪽 단추로 클릭하고 새 폴더를 선택하고 새 폴더CL의 이름을 로 지정합니다. 이 폴더를 만든 후 라는 새 클래스 ProductsCL.vb를 추가합니다.

CL이라는 새 폴더와 이름이 ProductsCL.vb 클래스를 추가합니다.

그림 2: 명명된 새 폴더 및 라는 CL 클래스 추가 ProductsCL.vb

클래스는 ProductsCL 해당 비즈니스 논리 계층 클래스(ProductsBLL)에 있는 것과 동일한 데이터 액세스 및 수정 방법 집합을 포함해야 합니다. 이러한 모든 메서드를 만드는 대신, CL에서 사용하는 패턴에 대한 느낌을 얻기 위해 여기에 몇 가지를 빌드해 보겠습니다. 특히 3단계에서 GetProducts() 및 메서드를 GetProductsByCategoryID(categoryID) 추가하고 4단계에서 오버로드를 UpdateProduct 추가합니다. 여가 시간에 나머지 ProductsCL 메서드와 CategoriesCL, EmployeesCLSuppliersCL 클래스를 추가할 수 있습니다.

2단계: 데이터 캐시 읽기 및 쓰기

이전 자습서에서 탐색한 ObjectDataSource 캐싱 기능은 내부적으로 ASP.NET 데이터 캐시를 사용하여 BLL에서 검색된 데이터를 저장합니다. 데이터 캐시는 ASP.NET 페이지 코드 숨김 클래스 또는 웹 애플리케이션 아키텍처의 클래스에서 프로그래밍 방식으로 액세스할 수도 있습니다. ASP.NET 페이지의 코드 숨김 클래스에서 데이터 캐시를 읽고 쓰려면 다음 패턴을 사용합니다.

' Read from the cache
Dim value as Object = Cache("key")
' Add a new item to the cache
Cache("key") = value
Cache.Insert(key, value)
Cache.Insert(key, value, CacheDependency)
Cache.Insert(key, value, CacheDependency, DateTime, TimeSpan)

Cache 클래스Insert 메서드에는 여러 오버로드가 있습니다. Cache("key") = valueCache.Insert(key, value) 는 동의어이며 둘 다 정의된 만료 없이 지정된 키를 사용하여 캐시에 항목을 추가합니다. 일반적으로 캐시에 항목을 추가할 때 종속성, 시간 기반 만료 또는 둘 다로 만료를 지정하려고 합니다. 다른 Insert 메서드의 오버로드 중 하나를 사용하여 종속성 또는 시간 기반 만료 정보를 제공합니다.

캐싱 계층의 메서드는 요청된 데이터가 캐시에 있는 경우 먼저 검사 있어야 하며, 이 경우 해당 위치에서 반환해야 합니다. 요청된 데이터가 캐시에 없는 경우 적절한 BLL 메서드를 호출해야 합니다. 다음 시퀀스 다이어그램과 같이 반환 값을 캐시한 다음 반환해야 합니다.

캐시 계층의 메서드는 사용 가능한 경우 캐시에서 데이터를 반환합니다.

그림 3: 캐싱 계층의 메서드는 사용 가능한 경우 캐시에서 데이터를 반환합니다.

그림 3에 표시된 시퀀스는 다음 패턴을 사용하여 CL 클래스에서 수행됩니다.

Dim instance As Type = TryCast(Cache("key"), Type)
If instance Is Nothing Then
    instance = BllMethodToGetInstance()
    Cache.Insert(key, instance, ...)
End If
Return instance

여기서 Type은 캐시에 저장되는 데이터의 형식입니다. 예를 들어 는 캐시 Northwind.ProductsDataTable항목을 고유하게 식별하는 키입니다. 지정된 키가 있는 항목이 캐시에 없으면 instanceNothing 해당 BLL 메서드에서 데이터를 검색하여 캐시에 추가합니다. 에 도달할 때까지 Return instanceinstance 캐시에서 또는 BLL에서 가져온 데이터에 대한 참조를 포함합니다.

캐시에서 데이터에 액세스할 때 위의 패턴을 사용해야 합니다. 언뜻 보기에 동등한 것처럼 보이는 다음 패턴에는 경합 상태를 도입하는 미묘한 차이가 포함되어 있습니다. 경주 조건은 산발적으로 자신을 드러내고 재현하기 어렵기 때문에 디버그하기가 어렵습니다.

If Cache("key") Is Nothing Then
    Cache.Insert(key, BllMethodToGetInstance(), ...)
End If
Return Cache("key")

이 두 번째 잘못된 코드 조각의 차이점은 캐시된 항목에 대한 참조를 로컬 변수에 저장하는 대신 데이터 캐시가 조건문 에서 Return직접 액세스된다는 것입니다. 이 코드에 도달하면 Cache("key") 가 이 아니라 Nothing문에 Return 도달하기 전에 시스템이 캐시에서 키를 제거한다고 상상해 보세요. 이 드문 경우에서 코드는 예상된 형식의 개체가 아닌 를 반환 Nothing 합니다.

참고

데이터 캐시는 스레드로부터 안전하므로 간단한 읽기 또는 쓰기를 위해 스레드 액세스를 동기화할 필요가 없습니다. 그러나 원자성이어야 하는 캐시의 데이터에 대해 여러 작업을 수행해야 하는 경우 스레드 안전을 보장하기 위해 잠금 또는 기타 메커니즘을 구현해야 합니다. 자세한 내용은 ASP.NET 캐시에 대한 액세스 동기화 를 참조하세요.

다음과 같이 메서드를 사용하여 Remove 데이터 캐시에서 항목을 프로그래밍 방식으로 제거할 수 있습니다.

Cache.Remove(key)

3단계: 클래스에서ProductsCL제품 정보 반환

이 자습서에서는 클래스 GetProducts() 에서 제품 정보를 반환하는 두 가지 메서드인 및 GetProductsByCategoryID(categoryID)ProductsCL 구현해 보겠습니다. 비즈니스 논리 계층 GetProducts()ProductsBL 클래스와 마찬가지로 CL의 메서드는 모든 제품에 대한 정보를 개체로 Northwind.ProductsDataTable 반환하고 GetProductsByCategoryID(categoryID) 지정된 범주의 모든 제품을 반환합니다.

다음 코드는 클래스의 메서드 일부를 보여 줍니다 ProductsCL .

<System.ComponentModel.DataObject()> _
Public Class ProductsCL
    Private _productsAPI As ProductsBLL = Nothing
    Protected ReadOnly Property API() As ProductsBLL
        Get
            If _productsAPI Is Nothing Then
                _productsAPI = New ProductsBLL()
            End If
            Return _productsAPI
        End Get
    End Property
    <System.ComponentModel.DataObjectMethodAttribute _
    (DataObjectMethodType.Select, True)> _
    Public Function GetProducts() As Northwind.ProductsDataTable
        Const rawKey As String = "Products"
        ' See if the item is in the cache
        Dim products As Northwind.ProductsDataTable = _
            TryCast(GetCacheItem(rawKey), Northwind.ProductsDataTable)
        If products Is Nothing Then
            ' Item not found in cache - retrieve it and insert it into the cache
            products = API.GetProducts()
            AddCacheItem(rawKey, products)
        End If
        Return products
    End Function
    <System.ComponentModel.DataObjectMethodAttribute _
        (DataObjectMethodType.Select, False)> _
    Public Function GetProductsByCategoryID(ByVal categoryID As Integer) _
        As Northwind.ProductsDataTable
        If (categoryID < 0) Then
            Return GetProducts()
        Else
            Dim rawKey As String = String.Concat("ProductsByCategory-", categoryID)
            ' See if the item is in the cache
            Dim products As Northwind.ProductsDataTable = _
                TryCast(GetCacheItem(rawKey), Northwind.ProductsDataTable)
            If products Is Nothing Then
                ' Item not found in cache - retrieve it and insert it into the cache
                products = API.GetProductsByCategoryID(categoryID)
                AddCacheItem(rawKey, products)
            End If
            Return products
        End If
    End Function
End Class

먼저 클래스 및 메서드에 DataObject 적용된 및 DataObjectMethodAttribute 특성을 확인합니다. 이러한 특성은 ObjectDataSource의 마법사에 정보를 제공하여 마법사 단계에 표시해야 하는 클래스와 메서드를 나타냅니다. CL 클래스 및 메서드는 프레젠테이션 계층의 ObjectDataSource에서 액세스되므로 디자인 타임 환경을 향상시키기 위해 이러한 특성을 추가했습니다. 이러한 특성 및 해당 효과에 대한 자세한 설명은 비즈니스 논리 계층 만들기 자습서를 참조하세요.

GetProducts()GetProductsByCategoryID(categoryID) 메서드에서 메서드에서 반환된 GetCacheItem(key) 데이터는 지역 변수에 할당됩니다. 곧 검사할 메서드는 GetCacheItem(key) 지정된 키를 기반으로 캐시에서 특정 항목을 반환합니다. 캐시에 이러한 데이터가 없으면 해당 ProductsBLL 클래스 메서드에서 검색된 다음 메서드를 사용하여 AddCacheItem(key, value) 캐시에 추가됩니다.

AddCacheItem(key, value) 메서드는 GetCacheItem(key) 각각 데이터 캐시, 읽기 및 쓰기 값과 인터페이스됩니다. 메서드는 GetCacheItem(key) 두 가지 중 더 간단합니다. 전달된 키를 사용하여 Cache 클래스의 값을 반환하기만 하면 됩니다.

Private Function GetCacheItem(ByVal rawKey As String) As Object
    Return HttpRuntime.Cache(GetCacheKey(rawKey))
End Function
Private ReadOnly MasterCacheKeyArray() As String = {"ProductsCache"}
Private Function GetCacheKey(ByVal cacheKey As String) As String
    Return String.Concat(MasterCacheKeyArray(0), "-", cacheKey)
End Function

GetCacheItem(key)는 제공된 대로 값을 사용하지 않고 대신 ProductsCache-가 앞에 추가된 키를 반환하는 메서드를 호출 GetCacheKey(key) 합니다. MasterCacheKeyArrayProductsCache 문자열을 보유하는 도 메서드에서 AddCacheItem(key, value) 사용됩니다. 잠시 후에 확인할 수 있습니다.

ASP.NET 페이지의 코드 숨김 클래스에서 클래스의 Cache 속성을 사용하여 Page 데이터 캐시에 액세스할 수 있으며 2단계에서 설명한 대로 와 같은 Cache("key") = value구문을 허용합니다. 아키텍처 내의 클래스에서 또는 HttpContext.Current.Cache를 사용하여 HttpRuntime.Cache 데이터 캐시에 액세스할 수 있습니다. Peter Johnson의 블로그 항목 HttpRuntime.Cache vs. HttpContext.Current.Cache는 대신 HttpContext.Current를 사용할 HttpRuntime 때 약간의 성능 이점을 제공합니다. 따라서 ProductsCL 은 을 사용합니다HttpRuntime.

참고

클래스 라이브러리 프로젝트를 사용하여 아키텍처를 구현하는 경우 및 HttpContext 클래스를 사용하려면 어셈블리에 대한 참조 System.WebHttpRuntime 추가해야 합니다.

캐시에서 ProductsCL 항목을 찾을 수 없는 경우 클래스의 메서드는 BLL에서 데이터를 가져와서 메서드를 사용하여 AddCacheItem(key, value) 캐시에 추가합니다. 캐시에 값을 추가하려면 60초 만료를 사용하는 다음 코드를 사용할 수 있습니다.

Const CacheDuration As Double = 60.0
Private Sub AddCacheItem(ByVal rawKey As String, ByVal value As Object)
    DataCache.Insert(GetCacheKey(rawKey), value, Nothing, _
        DateTime.Now.AddSeconds(CacheDuration), _
        System.Web.Caching.Cache.NoSlidingExpiration)
End Sub

DateTime.Now.AddSeconds(CacheDuration) 는 슬라이딩 만료가 없음을 나타내면서 System.Web.Caching.Cache.NoSlidingExpiration 60초 이후의 시간 기반 만료를 지정합니다. 이 Insert 메서드 오버로드에는 절대 및 슬라이딩 만료에 대한 입력 매개 변수가 있지만 둘 중 하나만 제공할 수 있습니다. 절대 시간과 시간 범위를 모두 지정하려고 하면 메서드가 Insert 예외를 throw합니다 ArgumentException .

참고

메서드의 AddCacheItem(key, value) 이 구현에는 현재 몇 가지 단점이 있습니다. 4단계에서 이러한 문제를 해결하고 해결하겠습니다.

4단계: 아키텍처를 통해 데이터를 수정할 때 캐시 무효화

캐싱 계층은 데이터 검색 메서드와 함께 데이터를 삽입, 업데이트 및 삭제하기 위해 BLL과 동일한 메서드를 제공해야 합니다. CL의 데이터 수정 메서드는 캐시된 데이터를 수정하지 않고 BLL의 해당 데이터 수정 메서드를 호출한 다음 캐시를 무효화합니다. 앞의 자습서에서 보았듯이 이는 캐싱 기능이 활성화되고 Insert, Update또는 Delete 메서드가 호출될 때 ObjectDataSource가 적용하는 것과 동일한 동작입니다.

다음 UpdateProduct 오버로드는 CL에서 데이터 수정 메서드를 구현하는 방법을 보여 줍니다.

<DataObjectMethodAttribute(DataObjectMethodType.Update, False)> _
Public Function UpdateProduct(productName As String, _
    unitPrice As Nullable(Of Decimal), productID As Integer) _
    As Boolean
    Dim result As Boolean = API.UpdateProduct(productName, unitPrice, productID)
    ' TODO: Invalidate the cache
    Return result
End Function

적절한 데이터 수정 Business Logic Layer 메서드가 호출되지만 응답이 반환되기 전에 캐시를 무효화해야 합니다. 그러나 클래스 및 GetProducts()GetProductsByCategoryID(categoryID) 메서드가 각각 다른 키를 GetProductsByCategoryID(categoryID) 사용하여 캐시에 항목을 추가하고 메서드가 각 고유 categoryID에 대해 다른 캐시 항목을 추가하기 때문에 ProductsCL 캐시를 무효화하는 것은 간단하지 않습니다.

캐시를 무효화할 때 클래스에 의해 ProductsCL 추가되었을 수 있는 모든 항목을 제거해야 합니다. 이 작업은 캐시 종속성을 메서드의 캐시 AddCacheItem(key, value) 에 추가된 각 항목과 연결하여 수행할 수 있습니다. 일반적으로 캐시 종속성은 캐시의 다른 항목, 파일 시스템의 파일 또는 Microsoft SQL Server 데이터베이스의 데이터일 수 있습니다. 종속성이 변경되거나 캐시에서 제거되면 연결된 캐시 항목이 캐시에서 자동으로 제거됩니다. 이 자습서에서는 클래스를 통해 추가된 모든 항목에 대한 캐시 종속성 역할을 하는 추가 항목을 캐시에 만들려고 합니다 ProductsCL . 이렇게 하면 캐시 종속성을 제거하면 이러한 모든 항목을 캐시에서 제거할 수 있습니다.

이 메서드를 통해 캐시에 AddCacheItem(key, value) 추가된 각 항목이 단일 캐시 종속성과 연결되도록 메서드를 업데이트해 보겠습니다.

Private Sub AddCacheItem(ByVal rawKey As String, ByVal value As Object)
    Dim DataCache As System.Web.Caching.Cache = HttpRuntime.Cache
    ' Make sure MasterCacheKeyArray[0] is in the cache - if not, add it
    If DataCache(MasterCacheKeyArray(0)) Is Nothing Then
        DataCache(MasterCacheKeyArray(0)) = DateTime.Now
    End If
    ' Add a CacheDependency
    Dim dependency As New Caching.CacheDependency(Nothing, MasterCacheKeyArray) _
        DataCache.Insert(GetCacheKey(rawKey), value, dependency, _
        DateTime.Now.AddSeconds(CacheDuration), _
        System.Web.Caching.Cache.NoSlidingExpiration)
End Sub

MasterCacheKeyArray 는 단일 값 ProductsCache를 보유하는 문자열 배열입니다. 먼저 캐시 항목이 캐시에 추가되고 현재 날짜와 시간이 할당됩니다. 캐시 항목이 이미 있는 경우 업데이트됩니다. 다음으로 캐시 종속성이 만들어집니다. CacheDependency 클래스의 생성자에는 여러 오버로드가 있지만 여기서 사용되는 클래스에는 두 개의 String 배열 입력이 예상됩니다. 첫 번째는 종속성으로 사용할 파일 집합을 지정합니다. 파일 기반 종속성을 Nothing 사용하지 않으려면 첫 번째 입력 매개 변수에 값이 사용됩니다. 두 번째 입력 매개 변수는 종속성으로 사용할 캐시 키 집합을 지정합니다. 여기서는 단일 종속성 를 MasterCacheKeyArray지정합니다. 그런 다음 가 CacheDependency 메서드에 Insert 전달됩니다.

이 수정을 통해 AddCacheItem(key, value)캐시를 무효화하는 것은 종속성을 제거하는 것만큼 간단합니다.

<DataObjectMethodAttribute(DataObjectMethodType.Update, False)> _
Public Function UpdateProduct(ByVal productName As String, _
    ByVal unitPrice As Nullable(Of Decimal), ByVal productID As Integer) _
    As Boolean
    Dim result As Boolean = API.UpdateProduct(productName, unitPrice, productID)
    ' Invalidate the cache
    InvalidateCache()
    Return result
End Function
Public Sub InvalidateCache()
    ' Remove the cache dependency
    HttpRuntime.Cache.Remove(MasterCacheKeyArray(0))
End Sub

5단계: 프레젠테이션 계층에서 캐싱 계층 호출

캐싱 계층의 클래스 및 메서드는 이러한 자습서 전체에서 검사한 기술을 사용하여 데이터로 작업하는 데 사용할 수 있습니다. 캐시된 데이터 작업을 보여 주려면 변경 내용을 클래스에 ProductsCL 저장한 다음 폴더에서 Caching 페이지를 열고 FromTheArchitecture.aspx GridView를 추가합니다. GridView의 스마트 태그에서 새 ObjectDataSource를 만듭니다. 마법사의 첫 번째 단계에서는 클래스를 ProductsCL 드롭다운 목록의 옵션 중 하나로 표시해야 합니다.

ProductsCL 클래스는 비즈니스 개체 Drop-Down 목록에 포함되어 있습니다.

그림 4: 클래스가 ProductsCL 비즈니스 개체 Drop-Down 목록에 포함되어 있습니다(전체 크기 이미지를 보려면 클릭).

ProductsCL선택한 후 다음을 클릭합니다. SELECT 탭의 드롭다운 목록에는 두 개의 항목 GetProducts() 이 있으며 GetProductsByCategoryID(categoryID) UPDATE 탭에는 단독 UpdateProduct 오버로드가 있습니다. GetProducts() SELECT 탭에서 메서드를 UpdateProducts 선택하고 업데이트 탭에서 메서드를 선택하고 마침을 클릭합니다.

ProductsCL 클래스의 메서드는 Drop-Down Lists 나열됩니다.

그림 5: ProductsCL 클래스의 메서드가 Drop-Down Lists 나열됩니다(전체 크기 이미지를 보려면 클릭).

마법사를 완료한 후 Visual Studio는 ObjectDataSource의 OldValuesParameterFormatString 속성을 로 original_{0} 설정하고 GridView에 적절한 필드를 추가합니다. OldValuesParameterFormatString 속성을 다시 기본값으로 변경하고 페이징, {0}정렬 및 편집을 지원하도록 GridView를 구성합니다. CL에서 UploadProducts 사용하는 오버로드는 편집된 제품의 이름과 가격만 허용하므로 이러한 필드만 편집할 수 있도록 GridView를 제한합니다.

이전 자습서에서는 , CategoryNameUnitPrice 필드에 대한 필드를 포함하도록 GridView를 ProductName정의했습니다. 이 서식 및 구조를 자유롭게 복제할 수 있습니다. 이 경우 GridView 및 ObjectDataSource의 선언적 태그는 다음과 유사하게 표시됩니다.

<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
    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") %>'></asp:Label>
            </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="ProductsDataSource" 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>

이 시점에서 캐싱 계층을 사용하는 페이지가 있습니다. 캐시가 작동하는 것을 보려면 클래스 및 GetProducts()UpdateProduct 메서드에서 ProductsCL 중단점을 설정합니다. 브라우저의 페이지를 방문하여 정렬 및 페이징할 때 코드를 단계별로 실행하여 캐시에서 가져온 데이터를 확인합니다. 그런 다음 레코드를 업데이트하고 캐시가 무효화되어 데이터가 GridView로 다시 설정되면 BLL에서 검색됩니다.

참고

이 문서와 함께 다운로드에 제공된 캐싱 계층이 완료되지 않았습니다. 여기에는 소수의 메서드만 제공하는 클래스 ProductsCL가 하나만 포함됩니다. 또한 단일 ASP.NET 페이지만 CL(~/Caching/FromTheArchitecture.aspx)을 사용하며 다른 모든 페이지는 여전히 BLL을 직접 참조합니다. 애플리케이션에서 CL을 사용하려는 경우 프레젠테이션 계층의 모든 호출은 CL로 이동해야 하며, CL의 클래스와 메서드는 현재 프레젠테이션 계층에서 사용되는 BLL의 클래스와 메서드를 포함해야 합니다.

요약

ASP.NET 2.0의 SqlDataSource 및 ObjectDataSource 컨트롤을 사용하여 프레젠테이션 계층에서 캐싱을 적용할 수 있지만, 이상적으로 캐싱 책임은 아키텍처의 별도 계층에 위임됩니다. 이 자습서에서는 프레젠테이션 계층과 비즈니스 논리 계층 사이에 상주하는 캐싱 계층을 만들었습니다. 캐싱 계층은 BLL에 있고 프레젠테이션 계층에서 호출되는 동일한 클래스 및 메서드 집합을 제공해야 합니다.

여기서 살펴보은 캐싱 계층 예제와 이전 자습서에서는 반응형 로드를 보여 줍니다. 사후 로드를 사용하면 데이터에 대한 요청이 이루어지고 캐시에서 데이터가 누락된 경우에만 데이터가 캐시에 로드됩니다. 실제로 필요하기 전에 캐시에 데이터를 로드하는 기술인 캐시에 데이터를 사전에 로드 할 수도 있습니다. 다음 자습서에서는 애플리케이션 시작 시 캐시에 정적 값을 저장하는 방법을 살펴볼 때 사전 로드의 예를 살펴보겠습니다.

행복한 프로그래밍!

저자 정보

7개의 ASP/ASP.NET 책의 저자이자 4GuysFromRolla.com 창립자인 Scott Mitchell은 1998년부터 Microsoft 웹 기술을 연구해 왔습니다. Scott은 독립 컨설턴트, 트레이너 및 작가로 일합니다. 그의 최신 책은 샘스 자신을 가르친다 ASP.NET 2.0 24 시간. 그는 에서 찾을 수있는 그의 블로그를 통해 또는 에 mitchell@4GuysFromRolla.comhttp://ScottOnWriting.NET도달 할 수 있습니다.

특별 감사

이 자습서 시리즈는 많은 유용한 검토자가 검토했습니다. 이 자습서의 수석 검토자는 테레사 머피였습니다. 예정된 MSDN 문서를 검토하시겠습니까? 그렇다면 에 줄을 놓습니다 mitchell@4GuysFromRolla.com.