블로그 이미지
다비도프

만나고, 고백하고, 가슴 떨리고, 설레이고, 웃고, 사랑하고, 키스하고, 함께하고..

Rss feed Tistory
카테고리 없음 2011. 4. 21. 18:00

WOWWOW

1. 로그인주소 설정

WTF 폴더 안에 Config.wtf 파일에 SET AccountName "메일주소" 를 추가시켜 놓으면 메일주소가 자동 입력됩니다.



2. 명함만들기

http://www.inven.co.kr/board/powerbbs.php?come_idx=17&query=view&p=1&my=&category=&sort=PID&orderby=&where=&name=subject&subject=&content=&keyword=%B8%ED%C7%D4&sterm=&iskin=&l=10803

결과
http://img845.imageshack.us/img845/2310/1303371180218449.png   [2011-04-21]



3. 데빌 UI 통합애드온 설치

1) 역할 표시
인터페이스 설정에서 PitBull Unit Frames 4.0로 들어가서 모듈을 선택한후에 Role <-이건가~ 활성화 하면 됩니다.

2) 대상의 대상 표시
Quartz3 설정

3) 패널 뒷배경 / 동상 삭제
패널 뒷배경 과 동상 모양 모두 /kgpanels config 에서 설정 가능합니다.

4) 골드표시 - 그림으로 표시하기
인터페이스 설정에서 색정보표시 체크 해제

5) 블랙에디션 대상창에 케릭터 얼굴
/pit 에서 설정가능합니다.

6) 단축키 보이기 설정
dominos설정창 들어가서 단축번호 보이기 체크해제했다가 다시 체크하면 보입니다

7) 버프 디버프 사이즈 조절
버프나 디버프 크기 , 나열되는 갯수 , 위치변경을 하고 싶으시면  bison 애드온을 깔아주시고 설정 하시면 간단히 변경완료 !!

8) 적의 초상화에 어그로 수치 표기
nameplate 다운 받아서 설정 해보세요~

-----------------------------------

일단 여기까지.


------------------------------------
2011.04.22

1. 데빌은 포기 -_-;

2. 추가 Addons 첨부



=====================================================================================

1. 정술 문양.
상급문양 : 번화, 용폭 고정..  화충/불정 넴드따라 스왑
주문양 : '번보 돌발톱 치유' 천둥 연번 넴드 따라 스왑
보조 : 맘대루
,
카테고리 없음 2009. 9. 7. 15:13

프로젝트 약어정리

SOA - Service Oriented Achitecture
서비스 지향 아키텍처(Service Oriented Architecture, 약칭 SOA 「에스오에이」혹은 「소아」로 발음)란 대규모 컴퓨터 시스템을 구축할 때의 개념으로 업무상에 일 처리에 해당하는 소프트웨어 기능을 서비스로 판단하여 그 서비스를 네트워크상에 연동하여 시스템 전체를 구축해 나가는 방법론이다. 업무 처리 변화를 시스템에 빠르게 반영하고자 하는 수요를 대응하기 위해 2004년부터 IT업계에서 주목을 하고 있다. 위키 : http://ko.wikipedia.org/wiki/SOA

ESB - Enterprise Service Bus

서비스들을 컴포넌트화된 논리적 집합으로 묶는 핵심 중간 도구이며, 비즈니스 프로세스 환경에 맞게 설계 및 전개 할 수 있는 아키텍처 패턴이다.

이 버스는 기본적인 메시징, EAI, 중개 기술을 사용하거나 J2EE시스템의 서비스 통합 버스와 같은 플랫폼 내의 구성요소를 사용하는 등 다양한 방법으로 구현될 수 있다. 또한 ESB는 EAI와 어플리케이션 서버 기술을 함께 조합하여 구현 가능하지만 이러한 구현 방식이 전반적인 아키텍처에 영향을 미치지 않아야 한다.

ESB는 전사 컴퓨팅 인프라스트럭처에 공통적으로 분산 되어 있는 여러 서비스, 어플리케이션, 다양한 데이터 등을 연결하는 지능형, 분산형, 트랜잭션형, 메시징 레이어로 작용한다. 또한 지능형 전송 기능과 라우팅 기능으로 동기 및 비동기 메시징 백본을 형성하여 메시지를 신뢰성있게 전달한다.

ESB는 개발자가 WSDL(Web Service Description Language)기반 표준 인터페이스에 의해 정의한 서비스, 즉 컴포넌트화된 비즈니스 기능을 API 또는 프로토콜에 관계없이 사용 및 호출하는 것을 가능하게 한다. WSDL은 추상화된 서비스 인터페이스 정의 부분, 재사용 가능한 프로토콜 바인딩 부분, 서비스를 제공하는 종단점(endpoint)부분으로 나뉘어 있다. 이것은 본질적으로 확장 가능하며, 필요에 따라 다양한 프로토콜을 동일한 서비스에 연결할 수 있도록 포트 및 바인딩을 위한 확장 요소를 제공한다.


EAI - Enterprise Application Integration
단일 조직 내부에서의 업무 프로세스를 최대한 단순화및 자동화 하기 위한 응용프로그램들의 연결을 의미 한다. 게다가 이미 존재하는 응용프로그램과 데이터구조에 대한 전면적인 수정 작업을 하지 않도록 도와 준다.

가트너(Gartner Group)의 인용에 따르면, "EAI 는 기업환경에서 연결되어 있는 어떠한 응용프로그램과 어떠한 원천 데이터 간에도 이뤄지는 구속 없는 공유"라고 정의 한다. [1]

EAI가 가지는 큰 의미는 서로다른 다양한 시스템간의 연결에 있다. 다른 운영체제(operating system)를 운영 중일 경우 그리고 다른 데이터베이스(database, DBMS)와 프로그래밍 언어(programming language)를 사용 중 이거나, 더 이상의 고객지원을 받을 수 없는 기존의 레거시 시스템(legacy system)간의 통합이 그것이다. 이런 경우, 시스템은 수정하기 힘들정도록 강하게 뭉쳐 있기 때문에, en:stovepipe system(강 종속시스템)이라 불린다.


SOAP - Simple Object Access Protocol
일반적으로 널리 알려진 HTTP,HTTPS,SMTP등을 사용하여 XML기반의 메시지를 컴퓨터 네트워크 상에서 교환하는 형태의 프로토콜이다. SOAP은 웹 서비스(Web Service)에서 기본적인 메시지를 전달하는 기반이 된다. SOAP에는 몇가지 형태의 메시지 패턴이 있지만, 보통의 경우 원격 프로시져 호출(Remote Procedure Call:RPC) 패턴으로, 네트워크 노드(클라이언트)에서 다른 쪽 노드(서버)쪽으로 메시지를 요청 하고, 서버는 메시지를 즉시 응답하게 된다. SOAP는 XML-RPC와 WDDX에서 envelope/header/body로 이루어진 구조와 전송(transport)와 상호 중립성(interaction neutrality)의 개념을 가져왔다.

SOAP은 XML을 근간으로 헤더와 바디를 조합하는 디자인 패턴으로 설계되어 있다. 「헤더」는 선택사항으로 반복이나 보안 및 트랜젝션을 정보로 하는 메타 정보를 가지고 있다. 「바디」부분은 주요한 정보인 정보를 가지고 있다.

위키 : http://ko.wikipedia.org/wiki/SOAP

ROI - Return On Investment (투자 수익)


ROI는 기업에서 정해진 자금의 사용에 대하여, 대체로 이익이나 비용절감 등 얼마나 많은 회수가 있느냐는 것을 말한다. ROI 추정은, 때로 주어진 제안서를 위한 비즈니스 사례를 계발하기 위해, 다른 접근방법과 함께 사용된다. 어떤 기업에 대한 전반적인 ROI는, 그 기업이 얼마나 잘 관리되고 있는지를 평가하는 방법으로 사용되기도 한다.

REST - Representational State Transfer

REST (Representational State Transfer)는 월드 와이드 웹과 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍처의 한 형식이다. 이 용어는 로이 필딩(Roy Fielding)의 2000년 박사학위 논문에서 소개되었다. 그는 하이퍼텍스트 전송 프로토콜 (HTTP)의 주요 저자들 가운데 한사람이다. 그 뒤로 이 개념은 네트워킹 문화에 널리 퍼졌다.

엄격한 의미로 REST는 네트워크 아키텍처 원리의 모음이다. 여기서 네트워크 아키텍처 원리란 리소스를 정의하고 리소스에 대한 주소를 지정하는 방법에 대한 개괄을 말한다. 간단한 의미로는, 도메인 지향 데이터를 HTTP위에서 SOAP이나 쿠키를 통한 세션 트랙킹 같은 부가적인 전송 레이어 없이, 전송하기 위한 아주 간단한 인터페이스를 말한다. 이 두 가지의 의미는 당연히 겹치는 부분과 충돌되는 부분이 있다. 필딩의 REST 아키텍처 형식을 따르면 HTTP 프로토콜을 사용하지 않은 채로 또 월드 와이드 웹에서 전송하지 않고도 아주 커다란 소프트웨어 시스템을 설계하는것도 가능하다. 또한 리모트 프로시져 콜을 이용하는 대신에 간단한 XMLHTTP 인터페이스(REST 원리에 부합하지는 않지만)를 이용해 설계하는것도 가능하다. 현실 세계에서의 REST 용어에 대한 이러한 두가지 의미는 기술 토론에서 종종 혼란을 야기한다.

필딩의 REST 원리를 따르는 시스템은 종종 RESTful이란 용어로 지칭된다. 열정적인 REST 옹호자들은 스스로를 RESTafrians 이라고 부른다.

위키 : http://ko.wikipedia.org/wiki/REST


UDDI - Universal Description, Discovery and Integration

UDDI(Universal Description, Discovery and Integration)는 웹 서비스 관련 정보의 공개와 탐색을 위한 표준이다. 서비스 제공자는 UDDI라는 서비스 소비자에게 이미 알려진 온라인 저장소에 그들이 제공하는 서비스들을 저장하게 되고, 서비스 소비자들은 그 저장소에 접근함으로써 원하는 서비스들의 목록을 찾을 수 있게 된다.

UDDI 비즈니스 등록은 다음과 같이 세 가지 구성요소를 갖는다.

  • 화이트 페이지(White Pages) — 주소, 연락처 등의 알려져 있는 식별자
  • 옐로 페이지(Yellow Pages) — 표준 분류법을 기반으로 한 산업 분류
  • 그린 페이지(Green Pages) — 비즈니스를 통해 노출된 서비스에 대한 기술 정보

URI - Uniform Resource Identifier
인터넷에 있는 자원을 나타내는 유일한 주소이다. URI의 존재는 인터넷에서 요구되는 기본조건으로서 인터넷 프로토콜에 항상 붙어다닌다. URI는 다음과 같은 요소로 구성된다.
  • 프로토콜 (HTTP 혹은 FTP) + : + // + 호스트이름 + 주소
  • 예: http://ko.wikipedia.org

URI의 하위개념으로 URL, URN 이 있다.


POC - Proof Of Concept

단순 개념 증명으로도 해석하기도 하지만 IT 업계에서 PoC는 신기술이 적용된 신제품을 직접 보고 어떻게 작동하는지를 시장에 소개하는 사전 검증의 개념으로 사용된다.
예를 들어 이미 시장에 나오지 않은 차기 프로세서 로드맵을 구매하기로 한 국내 모 대형 시중은행의 경우 계약 전 업체들을 불러 차기 제품의 성능과 기능을 미리 제시하도록 한뒤 장비를 정하는 PoC 과정을 거친다.
보통 시스템 구매 시 기존 제품의 경우 성능테스트를 뜻하는 BMT를 아직 양산되지 않은 신제품을 채택할 경우 PoC의 단계를 거치는 것이 일반적이며, 또 일부 업체들은 자사 신제품을 전시하고 시스템을 구현시키는 테스트실을 PoC로 부르기도 한다.


USN - Ubiquitous Sensor Network
센서 네트워크(sensor network)는 센서를 네트워크로 구성한 것을 말한다. 무선 센서 네트워크(WSN; wireless sensor network), 유비쿼터스 센서 네트워크(USN; ubiquitous sensor network) 등으로도 불린다.
인간 중심의 유비쿼터스 패러다임이 확대되면서 전 세계적으로 활발하게 연구되고 있는 기술 중의 하나이다.
유비쿼터스 센서 네트워크’는 대한민국에서 부르는 이름이며, 다음과 같은 특징이 있다.
  • USN 기술은 크게 RFID, WSN 등의 내용을 포함하고 있으며, 모든 사물에 적용되는 임베디드 무선 네트워크 기술이다.
  • USN 관련 소프트웨어 플랫폼으로는 TinyOS, Nano Qplus, Contiki, LiteOS 등이 있으며, 다양한 표준과 프로토콜을 지원한다.
  • USN 관련 표준으로는 IETF의 6LowPAN, ROLL, ZigBee, Wireless HART, ISA 등이 있다.
  • 2009년을 기준으로 2~3년 후에는 IPv6 를 접목한 USN 기술이 많이 확산될것으로 기대되고 있다.

MCI - Multi Channel Integration

MCA - Multi Channel Achitecture

BRMS - Business Rules Management System

BRE - Business Rules Engine

OLAP - OnLine Analytical Processing

OLTP - OnLine TransactionProcessing

GIS - Geometry Infomation System

BPM

EDA

BAM

CEP

EPN

BPEL

WSDL

CDC

WLI

WAS

Coherence

ETL(ETCL)

IoC (Inversion of Control)

IoC는 Inversion of Control의 약자로 한글로 "제어의 역전" 또는 "역제어"라고 부른다. 어떤 모듈이 제어를 가진다는 것은 "어떤 모듈을 사용할 것인지", "모듈의 함수는 언제 호출할 것인지" 등을 스스로 결정한다는 것을 의미한다. 이러한 제어가 역전되었다는 것은, 어떤 모듈이 사용할 모듈을 스스로 결정하는 것이 아니라 다른 모듈들에게 선택권을 넘겨준다는 것을 의미한다.


DI (Defendency Injection)

Defendency Injection이란 모듈간의 의존성을 모듈의 외부(컨테이너)에서 주입시켜주는 기능으로 Inversion of Control의 한 종류이다. 런타임시 사용하게 될 의존대상과의 관계를 Spring Framework가 총체적으로 결정하고, 그 결정된 의존특징을 런타임시 부여한다.

 AOP (Aspect Oriented Programming)
객체지향 프로그래밍(OOP)을 보완하는 개념으로, 어플리케이션을 객체지향적으로 모듈화하여 작성하더라도 다수의 객체들에 분산되어 중복적으로 존재하는 공통 관심사가  여전히 존재한다. AOP는 이를 횡단관심으로 분리하여 핵심관심과 엮어서 처리할 수 있는 방법을 제공한다.




,
PLEASURE 2009. 6. 24. 14:37

2009년 7월 휴가 +ㅁ+ㅋ

일정 : 7월 17일 ~ 19일 (2박 3일)
인원 : 7명 (판근,무열,성홍,영신,
회비 : 15만원 - 총 105만원
- 렌트 : 40만원
- 펜션 : 40만원
- 남는 금액은 휴가종료후 뿜빠이 ㅇㅅㅇㅋ
장소 : 낙산 해수욕장 (강원도 양양군 강현면 전진리)
숙소 : 네이플스토리 http://www.naples-house.net/new/main/home.htm





확인할 사항 :
1. 아침에 해돋이 - 낙산사 (전날밤에 일기예보 필수, 해뜨는시각 )
2. 척산온천 (http://www.choksan.co.kr/html/sub6_1.html)
3. 회 먹으러가기 (대포항 or 봉포항)

[봉포항 ~ 낙산해수욕장]


 
[봉포항 ~ 설악산]
 


[봉포항 ~ 낙산사]




[항구 정리]




[일출 시간]

 
,
카테고리 없음 2009. 5. 15. 17:49

사랑보단 사람 사람보다는 집안 집안보다는 돈


,
카테고리 없음 2009. 2. 26. 10:39

우대리님 요청 ^^

,
카테고리 없음 2007. 6. 20. 18:26

[올블로그] 키워드챔피언..?

사용자 삽입 이미지

올블로그에서 키워드 챔피언에 등록하랜다... ASP.NET으로...
MSDN에서 주워온거.. 여기저기 공부하면서 퍼온 거..투성인데..
확 등록해버려 ㅋㅋ -ㅅ-);;
,
카테고리 없음 2007. 5. 28. 10:22

[VS 2005] Membership, Role Management and Login Controls

VS2005 에서 패스워드 특수문자등을 포함하지 않은 암호도 쓸 수 있는 방법 
[출처 : 데브피아 : http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=13&MAEULNO=6&no=2&page=5]
1. Web.Config 설정
<membership defaultProvider="SqlProvider" userIsOnlineTimeWindow="15">
       <providers>
         <add name="SqlProvider"
           connectionStringName="LocalSqlServer"
           minRequiredNonalphanumericCharacters="0"
           minRequiredPasswordLength="4"
           type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken="/>
       </providers>      
</membership>

minRequiredPasswordLength="4" 을 보시면 아시듯이 암호를 4글자 이상으로 해주고.
minRequiredNonalphanumericCharacters="0" 을 추가하면 특수문자를 0문자로 했기때문에 '
특수문자를 넣지 않으셔도 됩니다.


2.  IIS 설정
IIS들어가셔서 현재 웹사이트의 속성중 "ASP.NET"텝에 보시면 2.0 으로 되어 있으시다면 "전역 구성 편집"으로 들어가시면요. 인증탭에 공급자 관리 들어가시면요.. 거기서 설정을 해주시면 위의 내용들을 쓰지 않으셔도 잘 됩니다
,
STUDY/SQL Cache Dependency 2007. 4. 30. 11:42

[Study] MSDN - Improved Caching in ASP.NET 2.0

Visual Studio 2005 Technical Articles
Improved Caching in ASP.NET 2.0
 

Stephen Walther
Microsoft Corporation

June 2004

Applies to:
   Microsoft ASP.NET 2.0
   Microsoft ASP.NET framework
   Microsoft SQL Server
   Microsoft Visual Studio .NET

Summary: Stephen Walther looks at the new caching features included in ASP.NET 2.0, and how you can use them to improve the performance and scalability of your ASP.NET applications. (20 printed pages)

Contents

Data Caching Made Easy
Using SQL Cache Invalidation
Using Post-Cache Substitution
Conclusion

The most dramatic way to improve the performance of a database driven Web application is through caching. Retrieving data from a database is one of the slowest operations that you can perform in a Web site. If, however, you can cache the database data in memory, then you can avoid accessing the database with every page request, and dramatically increase the performance of your application.

The one and only drawback to caching is the problem of stale data. If you cache the contents of a database table in memory, and the records in the underlying database table change, then your Web application will display old, inaccurate data. For certain types of data you might not care if the data being displayed is slightly out of date, but for other types of data—such as stock prices and auction bids—displaying data that is even slightly stale is unacceptable.

The initial release of the Microsoft ASP.NET framework did not provide a good solution to this problem. When using the ASP.NET 1.0 framework, you just had to live with this tradeoff between performance and stale data. Fortunately, the Microsoft ASP.NET 2.0 framework includes a new feature called SQL Cache Invalidation that solves this very problem.

In this article, you'll learn about many of the new caching enhancements in the ASP.NET 2.0 framework. First, you'll learn how caching support has been integrated into the new DataSource controls. Next, you'll learn how to configure and take advantage of SQL Cache Invalidation. Finally, we'll take a look at a new control introduced with the ASP.NET 2.0 framework, which enables you to inject dynamic content into a cached page: the Substitution control.

Data Caching Made Easy

One of the biggest changes in the ASP.NET 2.0 framework concerns how you access database data in an ASP.NET page. The ASP.NET 2.0 framework includes a new set of controls, known collectively as the DataSource controls, which enable you to represent a data source such as a database or an XML file.

In the ASP.NET 1.0 framework, you displayed database data with a control by binding the control to either a DataSet or a DataReader. In the ASP.NET 2.0 framework, you'll typically bind a control to a DataSource control instead. By taking advantage of the DataSource controls, you can build ASP.NET pages that display database data without writing any code for accessing the database.

When working with database data, you'll typically use one of the following three DataSource controls:

  • SqlDataSource—Represents any SQL data source, such as a Microsoft SQL Server or an Oracle database.
  • AccessDataSource—A specialized SqlDataSource control designed for working with a Microsoft Access database.
  • ObjectDataSource—Represents a custom business object that acts as a data source.

For example, imagine that you need to display a list of book titles retrieved from a database in a DropDownList control (see Figure 1). The page in Listing 1 illustrates how you can bind a DropDownList control to a SqlDataSource control.

Click here for larger image.

Figure 1. Using the SqlDataSource control to retrieve data

Listing 1. DisplayTitles.aspx

<html>
<head runat="server">
    <title>Display Titles</title>
</head>
<body>
    <form id="form1" runat="server">

        <asp:DropDownList 
            ID="DropDownList1" 
            DataSourceId="SqlDataSource1"
            DataTextField="Title"
            Runat="server" />
     
        <asp:SqlDataSource 
            ID="SqlDataSource1"
            ConnectionString="Server=localhost;database=Pubs"
            SelectCommand="SELECT Title FROM Titles"
            Runat="server" />
    
    </form>
</body>
</html>

Notice that the SqlDataSource control in Listing 1 is used to provide the connection string, and the SQL SELECT command used for retrieving the records from the database. The DropDownList control is bound to the SqlDataSource control through its DataSourceID property.

Caching with the DataSource Controls

The DataSource controls not only enable you to connect more easily to a database, they also make it easier for you to cache database data. Simply by setting a couple of properties on the SqlDataSource control, you can automatically cache the data represented by a DataSource control in memory.

For example, if you want to cache the Titles database table in memory for at least 10 minutes, you can declare a SqlDataSource control like this.

 <asp:SqlDataSource 
   ID="SqlDataSource1"
   EnableCaching="true"
   CacheDuration="600"
   ConnectionString="Server=localhost;database=Pubs"
   SelectCommand="SELECT Title FROM Titles"
   Runat="server" />

When the EnableCaching property has the value true, the SqlDataSource will automatically cache the data retrieved by the SelectCommand. The CacheDuration property enables you to specify, in seconds, how long the data should be cached before it is refreshed from the database.

By default, the SqlDataSource will cache data using an absolute expiration policy—every so many seconds, the data is refreshed from the database. You also have the option of enabling a sliding expiration policy. When the SqlDataSource is configured to use a sliding expiration policy, the data will not be dropped as long as it continues to be accessed. Employing a sliding expiration policy is useful whenever you have a large number of items that need to be cached, since this expiration policy enables you to keep only the most frequently accessed items in memory.

For example, the following SqlDataSourceControl is configured to use a sliding expiration policy of 10 minutes.

        <asp:SqlDataSource 
            ID="SqlDataSource1"
            EnableCaching="true"
            CacheExpirationPolicy="Sliding"
            CacheDuration="600"
            ConnectionString="Server=localhost;database=Pubs"
            SelectCommand="SELECT Title FROM Titles"
            Runat="server" />

Since the CacheExpirationPolicy property is set to the value Sliding and the CacheDuration property is set to the value 600, the data represented by this SqlDataSource will remain in memory just as long as it continues to be accessed within a 10 minute window.

Using SQL Cache Invalidation

SQL Cache Invalidation is one of the most anticipated new features of the ASP.NET 2.0 framework. By taking advantage of SQL Cache Invalidation, you get all of the performance benefits of caching without the problem of stale data. SQL Cache Invalidation enables you to automatically update data in the cache whenever the data changes in the underlying database.

Behind the scenes, SQL Cache Invalidation works by constantly polling the database to check for changes. Every so many milliseconds, the ASP.NET framework checks whether or not there have been any updates to the database. If the ASP.NET framework detects any changes, then any items added to the cache that depend on the database are removed from the cache (they are invalidated).

Note   Microsoft SQL Server 2005 supports a completely different method of SQL Cache Invalidation. You can configure SQL Server 2005 to notify your ASP.NET application whenever changes have been made to a database, a database table, or a database row. This means that the ASP.NET Framework does not need to constantly poll a SQL Server 2005 database for changes.

It is important to understand that SQL Cache Invalidation only works with Microsoft SQL Server version 7 and higher. You cannot use this feature with other databases such as Microsoft Access or Oracle.

You can use SQL Cache Invalidation when caching the output of an entire page, when working with the DataSource controls, or when working directly with the Cache object. We'll examine all three scenarios.

Configuring SQL Cache Invalidation

Before you can take advantage of SQL Cache Invalidation in your Web application, you must first perform some configuration steps. You must configure Microsoft SQL Server to support SQL Cache Invalidation and you must add the necessary configuration information to your application's Web configuration file.

There are two ways that you can configure SQL Server. You can either use the aspnet_regsql command line tool, or you can take advantage of the SqlCacheDependencyAdmin class.

Enabling SQL Cache Invalidation with ASPNET_REQSQL

The aspnet_regsql tool enables you to configure SQL Cache Invalidation from the command line. The aspnet_regsql tool is located in your Windows\Microsoft.NET\Framework\[version] folder. You must use this tool by opening a command prompt and navigating to this folder.

In order to support SQL Cache Invalidation when using the Pubs database, you need to execute the following command.

aspnet_regsql -E -d Pubs -ed

The -E option causes the aspnet_regsql tool to use integrated security when connecting to your database server. The -d option selects the Pubs database. Finally, the -ed option enables the database for SQL Cache Invalidation.

When you execute this command, a new database table named AspNet_SqlCacheTablesForChangeNotification is added to the database. This table contains a list of all of the database tables that are enabled for SQL Cache Invalidation. The command also adds a set of stored procedures to the database.

After you enable a database for SQL Cache Invalidation, you must select the particular tables in the database that you will enable for SQL Cache Invalidation. The following command enables the Titles database table.

aspnet_regsql -E -d Pubs -t Titles -et

The -t option selects a database table. The -et option enables a database table for SQL Cache Invalidation. You can, of course, enable multiple tables by re-executing this command for each database table.

When you execute this command, a trigger is added to the database table. The trigger fires whenever you make a modification to the table and it updates the AspNet_SqlCacheTablesForChangeNotification table.

Finally, if you want to get the list of tables that are currently enabled for SQL Cache Invalidation in a particular database, you can use the following command.

aspnet_regsql -E -d Pubs -lt

This method selects the list of tables from the AspNet_SqlCacheTablesForChangeNotification. Alternatively, you could retrieve this information by performing a query directly against this database table.

Using the SqlCacheDependencyAdmin Class

Behind the scenes, the aspnet_regsql tool uses the methods of the SqlCacheDependencyAdmin class to configure Microsoft SQL Server. If you prefer, you can use the methods of this class directly from within an ASP.NET page.

The SqlCacheDependencyAdmin class has five important methods:

  • DisableNotifications—Disables SQL Cache Invalidation for a particular database.
  • DisableTableForNotifications—Disables SQL Cache Invalidation for a particular table in a database.
  • EnableNotifications—Enables SQL Cache Invalidation for a particular database.
  • EnableTableForNotifications—Enables SQL Cache Invalidation for a particular table in a database.
  • GetTablesEnabledForNotifications—Returns a list of all tables enabled for SQL Cache Invalidation.

For example, the ASP.NET page in Listing 2 enables you to configure SQL Cache Invalidation for any table in the Pubs database (see Figure 2).

Click here for larger image.

Figure 2. Enabling SQL Cache Invalidation from an ASP.NET page

Listing 2. EnableSCI.aspx (C#)

<%@ Page Language="c#" %>
<%@ Import Namespace="System.Web.Caching" %>
<script runat="server">

    const string connectionString = "Server=localhost;Database=Pubs";

    void Page_Load()
    {
        if (!IsPostBack)
        {
            SqlCacheDependencyAdmin.EnableNotifications(
            connectionString);
            SqlDataSource1.SelectParameters.Add("connectionString", 
            connectionString);
        }
    }

    void EnableTable(Object s, EventArgs e)
    {
        try
        {
            SqlCacheDependencyAdmin.EnableTableForNotifications(
              connectionString, txtTableName.Text);
        }
        catch (Exception ex)
        {
            lblErrorMessage.Text = ex.Message;
        }
        txtTableName.Text = "";
    }

</script>

<html>
<head runat="server">
    <title>Enable SQL Cache Invalidation</title>
</head>
<body>
    <form id="form1" runat="server">
    
    <h1>SQL Cache Invalidation</h1>
    
    The following tables are enabled for SQL Cache Invalidation:
 
    <p>
    <asp:GridView id="grdTables" 
      DataSourceID="SqlDataSource1" CellPadding="10" 
      ShowHeader="false" Runat="Server" />
    </p>
    
    <asp:ObjectDataSource 
        ID="SqlDataSource1" 
        TypeName="System.Web.Caching.SqlCacheDependencyAdmin"
        SelectMethod="GetTablesEnabledForNotifications"
        Runat="Server" />
    <p>
    <asp:Label ID="lblErrorMessage" EnableViewState="false" 
      ForeColor="red" Runat="Server" />
    </p>

     <asp:TextBox ID="txtTableName" Runat="Server" /> 
     <asp:Button Text="Enable Table" OnClick="EnableTable" 
       Runat="Server" /> 
 
    </form>
</body>
</html>

Listing 2. EnableSCI.aspx (Visual Basic .NET)

<%@ Page Language="vb" %>
<%@ Import Namespace="System.Web.Caching" %>
<script runat="server">

    Const connectionString As String = "Server=localhost;Database=Pubs"

    Sub Page_Load()
    
        If Not IsPostBack Then
            SqlCacheDependencyAdmin.EnableNotifications( _
            connectionString)
            SqlDataSource1.SelectParameters.Add("connectionString", _
            connectionString)
        End If
    End Sub

    Sub EnableTable(ByVal s As Object, ByVal e As EventArgs)
    
        Try
        
            SqlCacheDependencyAdmin.EnableTableForNotifications( _
              connectionString, txtTableName.Text)
        Catch ex As Exception
            lblErrorMessage.Text = ex.Message
        End Try
        txtTableName.Text = ""
    End Sub

</script>

<html>
<head id="Head1" runat="server">
    <title>ConfigureSCI</title>
</head>
<body>
    <form id="form1" runat="server">
    
    <h1>SQL Cache Invalidation</h1>
    
    The following tables are enabled for SQL Cache Invalidation:
 
    <p>
    <asp:GridView id="grdTables" DataSourceID="SqlDataSource1" 
       CellPadding="10" ShowHeader="false" Runat="Server" />
    </p>
    
    <asp:ObjectDataSource 
        ID="SqlDataSource1" 
        TypeName="System.Web.Caching.SqlCacheDependencyAdmin"
        SelectMethod="GetTablesEnabledForNotifications"
        Runat="Server" />
    <p>
    <asp:Label ID="lblErrorMessage" EnableViewState="false" 
      ForeColor="red" Runat="Server" />
    </p>

     <asp:TextBox ID="txtTableName" Runat="Server" /> 
     <asp:Button ID="Button1" Text="Enable Table" 
      OnClick="EnableTable" Runat="Server" /> 
 
    </form>
</body>
</html>

In Listing 2, the connectionString constant is used to select the database for which SQL Cache Invalidation is enabled (You can change the value of this constant when you want to enable SQL Cache Invalidation for a database other than the Pubs database). Within the Page_Load method, the EnableNotifications method on the SqlCacheDependencyAdmin class is called to enable SQL Cache Invalidation for the database specified by the connectionString constant.

The GridView in Listing 2 displays all of the database tables that are currently enabled for SQL Cache Invalidation. The GridView is bound to an ObjectDataSource control that calls the GetTablesneabledForNotifications method for its SelectMethod.

Finally, you can use the page in Listing 2 to enable additional tables for SQL Cache Invalidation. When you enter the name of a table in the textbox and click the Enable Table button, the EnableTableForNotifications method is called.

Web Configuration Settings for SQL Cache Invalidation

The next step, before you can use SQL Cache Invalidation in your ASP.NET application, is to update your Web configuration file. You need to configure the ASP.NET framework to poll the databases that you have enabled for SQL Cache Invalidation.

The Web configuration file in Listing 3 contains the necessary configuration information to poll the Pubs database.

Listing 3. Web.Config

<configuration>
      
  <connectionStrings>
    <add name="mySqlServer" 
      connectionString="Server=localhost;Database=Pubs" />
  </connectionStrings>
        
  <system.web>

    <caching>
      <sqlCacheDependency enabled="true">
      <databases>
      <add
            name="Pubs"
            connectionStringName="mySqlServer"
            pollTime="60000" />
      </databases>
      </sqlCacheDependency>
    </caching>
    </system.web>
</configuration>

The Web configuration file in Listing 3 contains two sections. The <connectionStrings> section is used to create a database connection string to the Pubs database named mySqlServer.

The caching section is used to configure the SQL Cache Invalidation polling. Within the <databases> subsection, you can list one or more databases that you want to poll for changes. In Listing 3, the database represented by the mySqlServer is polled once a minute (every 60000 milliseconds).

You can specify different polling intervals for different databases. The server must do a little bit of work every time the database is polled for changes. If you don't expect the data in the database to change very often, then you can increase the polling interval.

Using SQL Cache Invalidation with Page Output Caching

Now that we've gotten all of the configuration steps for SQL Cache Invalidation out of the way, we can start taking advantage of it in our ASP.NET pages. One way that you can use SQL Cache Invalidation is with page output caching. Page output caching enables you to cache the entire rendered contents of a page in memory. By taking advantage of SQL Cache Invalidation, you can automatically update the cached page when, and only when, a change is made to a database table.

For example, the page in Listing 4 displays the contents of the Titles database table in a GridView control. At the top of the page, the OutputCache directive is used to cache the contents of the page in memory. The SqlDependency attribute causes the page to be updated whenever the Titles database table changes.

Listing 4. OutputCacheTitles.aspx

<%@ OutputCache SqlDependency="Pubs:Titles" 
    Duration="6000" VaryByParam="none" %>
<html>
<head runat="server">
    <title>Output Cache Titles</title>
</head>
<body>
    <form id="form1" runat="server">
    
    <%= DateTime.Now %>

    <asp:GridView 
      ID="grdTitles" 
      DataSourceID="SqlDataSource1" 
      Runat="Server" />    
    
    <asp:SqlDataSource
      ID="SqlDataSource1"
      SelectCommand="Select * FROM Titles"
      ConnectionString="<%$ ConnectionStrings:mySqlServer %>"
      Runat="Server" />
    
    </form>
</body>
</html>

Notice that the SqlDependency attribute references the name of the database defined within the Web configuration file. Since we specified that the Pubs database should be polled once every minute for changes, if a change is made to the database the page in Listing 4 will be updated within a minute.

You can list more than one database and/or more than one database table for the value of the SqlDependency attribute. To create more than one dependency, simply separate each dependency with a semicolon.

Using SQL Cache Invalidation with the DataSource Control

As an alternative to using SQL Cache Invalidation with page output caching, you can use SQL Cache Invalidation directly with the DataSource controls. You should consider using SQL Cache Invalidation with the DataSource controls when you need to work with the same database data in multiple pages. The SqlDataSource, AccessDataSource, and ObjectDataSource controls all support a SqlCacheDependency property.

For example, the page in Listing 5 uses the SQL Cache Invalidation with the SqlDataSource control.

Listing 5. SqlDataSourceCaching.aspx

<html>
<head id="Head1" runat="server">
    <title>SqlDataSource Caching</title>
</head>
<body>
    <form id="form1" runat="server">

        <%= DateTime.Now %>

        <asp:GridView 
            ID="grdTitles" 
            DataSourceId="SqlDataSource1"
            Runat="server" />
            
        <asp:SqlDataSource 
            ID="SqlDataSource1" 
            EnableCaching="true"
            SqlCacheDependency="Pubs:Titles"
            SelectCommand="select * from titles"
            ConnectionString="<%$ ConnectionStrings:mySqlServer %>"
            Runat="server" />
   
    </form>
</body>
</html>

In Listing 5, the SqlDataSource control is declared with both an EnableCaching attribute and a SqlCacheDependency attribute. The SqlCacheDependency property uses the same syntax as the OutputCache directive's SqlDependency attribute. You list the name of the database, followed by the name of the database table.

Using SQL Cache Invalidation with the Cache Object

A final option is to use SQL Cache Invalidation with the Cache object. This option provides you with the greatest degree of programmatic control over SQL Cache Invalidation.

To use SQL Cache Invalidation with the Cache object, you need to create an instance of the SqlCacheDependency object. You can use the SqlCacheDependency object when inserting a new object into the Cache with the Insert method.

For example, the page in Listing 6 displays the number of records in the Titles database table. The count is cached with a dependency on the underlying database table.

Listing 6. DisplayTitleCount.aspx (C#)

<%@ Page Language="c#" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="server">

    void Page_Load() 
    {
        int count = 0;

        if (Cache["TitleCount"] != null)
        {
            count = (int)Cache["TitleCount"];
        }
        else
        {
            string connectionString = 
              ConfigurationSettings.ConnectionStrings[
              "mySqlServer"].ConnectionString;
            SqlConnection con = new SqlConnection(connectionString);
            SqlCommand cmd = new 
              SqlCommand("SELECT Count(*) FROM Titles", con);
            con.Open();
            count = (int)cmd.ExecuteScalar();
            con.Close();
            Cache.Insert("TitleCount", count, 
              new SqlCacheDependency("Pubs", "Titles"));
        }
        lblTitleCount.Text = count.ToString();
    }

</script>

<html>
<head runat="server">
    <title>Display Title Count</title>
</head>
<body>
    <form id="form1" runat="server">

    <asp:Label ID="lblTitleCount" Runat="Server" />    
    
    </form>
</body>
</html>

Listing 6. DisplayTitleCount.aspx (Visual Basic .NET)

<%@ Page Language="vb" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="server">

    Sub Page_Load()
    
        Dim count As Integer = 0

        If Not Cache("TitleCount") Is Nothing Then
            count = Convert.ToInt32(Cache("TitleCount"))
        Else
            Dim connectionString As String = _
              ConfigurationSettings.ConnectionStrings( _
              "mySqlServer").ConnectionString
            Dim con As New SqlConnection(connectionString)
            Dim cmd As New _
              SqlCommand("SELECT Count(*) FROM Titles", con)
            con.Open()
            count = Convert.ToInt32(cmd.ExecuteScalar())
            con.Close()
            Cache.Insert("TitleCount", count, _
              new SqlCacheDependency("Pubs", "Titles"))
        End If
        
        lblTitleCount.Text = count.ToString()
    End Sub

</script>

<html>
<head id="Head1" runat="server">
    <title>Display Titles Count</title>
</head>
<body>
    <form id="form1" runat="server">

    <asp:Label ID="lblTitleCount" Runat="Server" />    
    
    </form>
</body>
</html>

Using Post-Cache Substitution

There are many situations in which you need to cache part of a page, but not the entire page. For example, on the home page of your Web site, you might want to display both a random banner advertisement and the records from a database table. If you cache the entire page, then every user will see the same banner advertisement on each and every page request.

One way to handle this problem of mixing dynamic and cached content is to use Web User Controls. Since you can add an OutputCache directive to a Web User Control, you can cache the contents of a Web User Control even when you do not cache the contents of the containing page.

Sometimes, however, this gets things backwards. You can use Web User Controls to add cached content to a dynamic page. In many situations, however, what you really want to do is add dynamic content to a cached page. For example, imagine that you want to cache the entire contents of a page, except for one little area where you want to display the current user's username. This is a perfect situation in which you'll want to take advantage of post-cache substitution.

The ASP.NET 2.0 framework introduces a new control called the Substitution control. You can use the Substitution control to inject dynamic content into a cached page. The page in Listing 7 uses the Substitution control to inject a username into cached content (see Figure 3).

Figure 3. Displaying a username with the Substitution control

Listing 7. PostCacheSubstitution.aspx (C#)

<%@ Page Language="C#" %>
<%@ OutputCache Duration="6000" VaryByParam="none" %>

<script runat="server">

    static string DisplayUsername(HttpContext context) 
    {
        if (!context.Request.IsAuthenticated)
            return "Anonymous";
        else
            return context.User.Identity.Name;
    }

</script>

<html>
<head runat="server">
    <title>Post Cache Substitution</title>
</head>
<body>
    <form id="form1" runat="server">
    
    Welcome <asp:Substitution 
      MethodName="DisplayUsername" Runat="Server" />!
    
    <p>
    This page is cached as you'll notice from the fact that the time
    <%= DateTime.Now.ToString("t") %> never changes.
    </p>
        
    </form>
</body>
</html>

Listing 7. PostCacheSubstitution.aspx (Visual Basic .NET)

<%@ Page Language="vb" %>
<%@ OutputCache Duration="6000" VaryByParam="none" %>

<script runat="server">

    Shared Function DisplayUsername(ByVal context As HttpContext) _
      As String
        If Not context.Request.IsAuthenticated Then
            Return "Anonymous"
        Else
            Return context.User.Identity.Name
        End If
    End Function

</script>

<html>
<head id="Head1" runat="server">
    <title>Post Cache Substitution</title>
</head>
<body>
    <form id="form1" runat="server">
    
    Welcome <asp:Substitution 
      ID="Substitution1" 
      MethodName="DisplayUsername" 
      Runat="Server" />!
    
    <p>
    This page is cached as you'll notice from the fact that the time
    <%= DateTime.Now.ToString("t") %> never changes.
    </p>
       
     </form>
</body>
</html>

The Substitution control has one important property: the MethodName property. The MethodName property is used to represent the method that is called to return the dynamic content. The method called by the Substitution control must be a static method (shared in the Visual Basic .NET world). Furthermore, the method must have one parameter that represents the current HttpContext.

In the ASP.NET 2.0 framework, the AdRotator control has been modified to support post-cache substitution. If you add the AdRotator control to a page that uses the OutputCache directive, the AdRotator control is automatically exempt from its containing page's caching policy.

Conclusion

Caching has a dramatic impact on the performance of database-driven Web applications. Fortunately, the ASP.NET 2.0 framework includes a number of significant new enhancements that make it easier to take advantage of caching in your applications.

The new DataSource controls include properties that make it easy to cache database data in memory. By taking advantage of the DataSource controls, you can retrieve database data and cache the data without writing a single line of code.

The new support for SQL Cache Invalidation enables you to automatically reload database data in the cache whenever the data is modified in the underlying database. This feature provides you with all the performance benefits of caching, without the worries of stale data.

Finally, the new Substitution control enables you to more easily mix dynamic content in a cached page. The Substitution control gives you an island of dynamic content in an otherwise cached page.

Related Books


About the author

Stephen Walther wrote the best-selling book on ASP.NET, ASP.NET Unleashed. He was also the architect and lead developer of the ASP.NET Community Starter Kit, a sample ASP.NET application produced by Microsoft. He has provided ASP.NET training to companies across the United States, including NASA and Microsoft, through his company Superexpert (http://www.superexpert.com).

,
STUDY/SQL Cache Dependency 2007. 4. 30. 11:31

[Study] ADO.NET 2.0의 쿼리 알림 (SqlDependency)

ADO.NET 2.0의 쿼리 알림

 

Bob Beauchemin
DevelopMentor

2005년 4월
업데이트한 날짜: 2005년 6월

적용 대상:
   ADO.NET 2.0

요약: ADO.NET 2.0 및 SQL Server 2005에 제공되는 새로운 알림 기술을 사용하여 데이터 변경을 다루는 방법을 배워 보십시오.

목차

소개
캐시 솔루션을 제공하는 SqlDependency
SQL Server 2005의 쿼리 알림
최종 사용자 또는 캐시로 알림 발송
데이터베이스 클라이언트에서 쿼리 알림 사용
SqlDependency 사용
SqlNotificationRequest 사용
ASP.NET에서 SqlCacheDependency 사용
향상된 알림 기능
알림을 사용하지 않는 경우: 교훈
결론

소개

모든 실제 관계형 데이터베이스 응용 프로그램에는 으레 많은 조회 테이블이 들어 있습니다. 그래픽 사용자 인터페이스를 코딩하는 경우 이러한 조회 테이블은 드롭다운 목록 상자를 채우는 목록으로 나타납니다. 필자는 조회 테이블을 읽기 전용 테이블과 읽기 위주(read-mostly) 테이블의 두 가지 유형으로 분류합니다. 이들 간의 차이는 테이블의 변경을 유발하는 부분에 있습니다. 직원 회의나 사용자 회의를 통해 테이블을 변경하는 경우는 읽기 전용 테이블로 볼 수 있으며, 회사의 제품 범주가 포함된 테이블은 이에 대한 좋은 예입니다. 이러한 테이블은 회사에서 신제품을 출시하거나 회사가 재편되지 않는 한 변경되지 않습니다. 읽기 위주 테이블은 비교적 일관되게 유지되지만 최종 사용자가 변경할 수 있는 목록입니다. 이러한 테이블은 대개 드롭다운 목록이 아닌 콤보 상자에 나타납니다. 읽기 위주 테이블의 예로는 호칭(term-of-greeting) 테이블을 들 수 있습니다. 응용 프로그램 디자이너는 대개 Ms., Mr., Mrs. 및 Dr. 같은 일반적인 호칭을 생각할 수 있지만 한 번도 생각해 본 적 없는 호칭을 추가하려는 사용자도 늘 있게 마련입니다. 이러한 일이 얼마나 흔한 경우인지를 보여 주는 예로, 필자가 최근 작업한 중간 크기 제품에는 제3 정규형 관계형 데이터베이스에 350-400개의 테이블이 들어 있었습니다. 이 중 250개 정도가 읽기 전용 또는 읽기 위주 테이블인 것으로 추정됩니다.

3계층 응용 프로그램의 대표적인 예라 할 수 있는 일반적인 웹 응용 프로그램에서는 이러한 유형의 테이블을 가능한 한 많이 캐시하게 됩니다. 이렇게 하면 데이터베이스로의 왕복 횟수는 물론 데이터베이스에서의 쿼리 로드를 줄여 신규 주문 같은 사용 사례에서 응답 성능을 높일 수 있습니다. 읽기 전용 테이블의 경우에는 항상 테이블을 캐시에 유지하고 데이터베이스 관리자(DBA)가 테이블을 다시 로드해야 할 경우에만 이따금 캐시를 다시 로드할 수 있도록 하므로 캐시 작업이 간단합니다. 조직에서 기본 데이터베이스 구조와 콘텐츠를 변경하는 회의를 하는 경우는 아마 거의 없을 것입니다. 중간 계층 캐시에서 읽기 위주 조회 테이블을 새로 고치면 약간의 문제가 발생할 수 있습니다. 일정에 따라 캐시를 간헐적으로 새로 고쳐도 원하는 동작이 만들어지지 않을 뿐 아니라, 사용자는 다른 사용자의 변경 내용을 바로 확인하지 못합니다. 지원 담당자가 다른 응용 프로그램을 사용하여 새 항목을 추가하고 이를 사용하려는 친구에게 인스턴트 메신저 메시지를 보낼 수 있겠지만, 선택한 친구 목록은 새 항목에 포함되지 않습니다. 게다가 다른 사용자가 "누락된 목록 항목"을 다시 추가하려고 하면 항목이 이미 존재한다는 내용의 데이터베이스 오류 메시지가 표시됩니다. 읽기 위주 테이블에 "업데이트 지점"이 둘 이상인 경우에는 대개 이러한 문제로 인해 해당 테이블의 캐시 작업이 이루어지지 않습니다.

예전의 프로그래머들은 메시지 대기열을 사용하는 수작업 솔루션, 파일에 쓰는 트리거 또는 응용 프로그램 외부의 누군가가 읽기 위주 테이블을 업데이트하면 이를 캐시에 알리는 대역 외 프로토콜에 의존했습니다. 이러한 "알림(signaling)" 솔루션은 단순히 행이 추가 또는 변경되었으므로 캐시를 새로 고쳐야 한다는 내용을 캐시에 알리는 역할만 합니다. 특정 행이 변경 또는 추가되었음을 캐시에 알리는 것은 조금 다른 문제이며, 분산 데이터베이스 및 트랜잭션 또는 병합 복제 영역에 해당됩니다. 오버헤드가 낮은 알림 솔루션에서는 프로그램에 "잘못된 캐시"라는 메시지가 표시되면 전체 캐시를 새로 고치기만 할 뿐입니다.

캐시 솔루션을 제공하는 SqlDependency

SQL Server 2005 및 ADO.NET 2.0 사용자는 이제 SqlClient 데이터 공급자와 쿼리 알림이라는 데이터베이스에 기본 제공되는 알림 솔루션을 사용할 수 있습니다. 이는 이러한 일상적인 문제를 해결하는 사용이 편리한 최초의 기본 제공 솔루션입니다. 쿼리 알림은 ASP.NET 2.0의 기본 기능에서도 직접 지원됩니다. ASP.NET 캐시는 알림에 등록할 수 있으며 이 알림은 AST.NET에서 사용되는 페이지 및 페이지 조각 캐시와도 함께 사용할 수 있습니다.

이처럼 유용한 기능을 수행하는 인프라는 SQL Server 2005 쿼리 엔진, SQL Server Service Broker, 시스템 저장 프로시저인 sp_DispatcherProc, ADO.NET SqlNotification(System.Data.Sql.SqlNotificationRequest), SqlDependency(System.Data.SqlClient.SqlDependency) 클래스 및 ASP.NET Cache(System.Web.Caching.Cache) 클래스로 구성되어 있습니다. 요컨대 이 인프라는 다음과 같이 작동합니다.

  1. 각 ADO.NET SqlCommand에는 알림 요청을 나타내는 Notification 속성이 들어 있습니다. SqlCommand가 실행될 때 Notification 속성이 있으면 알림 요청을 나타내는 네트워크 프로토콜(TDS)이 요청에 추가됩니다.
  2. SQL Server는 쿼리 알림 인프라를 사용하여 요청된 알림에 대해 구독을 등록하고 명령을 실행합니다.
  3. SQL Server는 SQL DML 문에서 처음에 반환된 행 집합을 변경시킬 수 있는 부분이 있는지 "감시"합니다. 변경이 발생하면 Service Broker 서비스로 메시지가 전송됩니다.
  4. 이 메시지는 다음과 같은 작업을 수행합니다.
    1. 등록된 클라이언트에 다시 알림이 발생하도록 합니다.
    2. 고급 클라이언트가 사용자 지정 처리를 할 수 있도록 Service Broker 서비스 대기열에 그대로 유지됩니다.

그림 1. 쿼리 알림의 상위 개요

ASP.NET SqlCacheDependency(System.Web.Caching.SqlCacheDependency) 클래스 및 OutputCache 지시문은 SqlDependency를 통해 자동 알림 기능을 사용합니다. 더 많은 컨트롤이 필요한 ADO.NET 클라이언트는 SqlNotificationRequest를 사용하고 Service Broker 대기열을 수동으로 처리하여 필요한 사용자 지정 구문을 모두 구현할 수 있습니다. Service Broker에 대한 자세한 설명은 이 기사에서는 다루지 않지만 샘플 서적의 A First Look at SQL Server 2005 for Developers(영문) 부분과 Roger Wolter가 저술한 "A First Look at SQL Server 2005 Service Broker"(영문) 기사를 참조하면 이를 이해하는 데 많은 도움이 될 것입니다.

계속하기 전에, 행 집합이 변경되면 SqlNotificationRequest 또는 SqlDependency에 각각 알림 메시지가 하나씩 전달되는 부분을 확실히 이해하고 넘어가야 합니다. 이 메시지는 변경을 유발하는 부분이 데이터베이스 INSERT 문이든, 하나 이상의 행을 삭제하는 DELETE 문이든, 하나 이상의 행을 업데이트하는 UPDATE 문이든 관계없이 동일합니다. 알림에 변경된 특정 행 또는 변경된 수와 관련된 정보는 들어 있지 않습니다. 캐시 개체나 사용자의 응용 프로그램에서 이러한 단일 변경 메시지를 받으면 전체 행 집합을 새로 고치고 알림에 다시 등록하는 방법 밖에는 없습니다. 여러 개의 메시지를 수신하지는 않으며 하나의 메시지가 발생한 후에는 데이터베이스의 사용자 구독이 종료됩니다. 또한 쿼리 알림 프레임워크는 이벤트에 대한 알림은 많이 받을수록 좋다는 것을 전제로 하여 작동합니다. 알림은 행 집합이 변경될 때는 물론 행 집합에 참여한 테이블이 삭제 또는 변경될 때, 데이터베이스를 재활용할 때 등과 같은 경우에도 전송됩니다. 캐시 또는 프로그램의 응답은 캐시된 데이터를 새로 고치고 알림에 다시 등록하는 것과 관계없이 대개 동일합니다.

지금까지 관련된 일반적인 구문에 대해 알아보았으므로 이제는 다음과 같은 세 가지 관점에서 작동 원리를 자세히 살펴보겠습니다.

  1. SQL Server의 쿼리 알림 구현 방식 및 옵션 발송자의 작동 원리
  2. SqlClientSqlDependencySqlNotificationRequest가 클라이언트/중간 계층에서 작동하는 방식
  3. ASP.NET 2.0의 SqlDependency 지원 방식

SQL Server 2005의 쿼리 알림

SQL Server는 서버 수준에서 클라이언트의 쿼리를 일괄적으로 처리합니다. 각 쿼리(여기서 쿼리는 SqlCommand.CommandText 속성임)에는 일괄 처리가 하나만 포함될 수 있지만, 일괄 처리에는 여러 개의 T-SQL 문이 들어 있을 수 있습니다. SqlCommand는 여러 개의 T-SQL 문이 포함될 수 있는 저장 프로시저나 사용자 정의 함수를 실행하는 데도 사용할 수 있습니다. 또한 SQL Server 2005에서는 클라이언트의 쿼리에 알림을 배달하는 Service Broker 서비스 이름, 알림 ID(문자열) 및 알림 시간 제한과 같은 세 가지 추가 정보가 포함될 수 있습니다. 쿼리 요청에 이러한 세 가지 정보가 나타나 있고 요청에 SELECT 또는 EXECUTE 문이 들어 있으면 SQL Server는 해당 쿼리에 의해 만들어진 모든 행 집합에 다른 SQL Server 세션의 변경 내용이 있는지 "감시"하게 됩니다. 저장 프로시저를 실행할 때처럼 여러 개의 행 집합이 생성되는 경우 SQL Server는 모든 행 집합을 "감시"합니다.

그렇다면 여기서 행 집합을 "감시"한다는 것은 어떤 의미이며 SQL Server는 이를 어떤 식으로 수행할까요? 행 집합의 변경 내용을 탐지하는 일은 SQL Server 엔진에서 수행하는 작업의 일부이며, 인덱싱된 뷰의 동기화를 위한 SQL Server 2000의 변경 탐지 기능부터 적용된 메커니즘이 사용됩니다. Microsoft는 SQL Server 2000부터 인덱싱된 뷰 개념을 도입했습니다. SQL Server의 뷰는 하나 이상의 테이블에 있는 열에 대한 쿼리로 구성되어 있습니다. 뷰 이름은 테이블 이름처럼 사용할 수 있습니다. 예를 들면 다음과 같습니다.

CREATE VIEW WestCoastAuthors
AS
SELECT * FROM authors
  WHERE state IN ('CA', 'WA', 'OR')

이제 뷰를 다음과 같이 쿼리의 테이블처럼 사용할 수 있습니다.

SELECT au_id, au_lname FROM WestCoastAuthors
  WHERE au_lname LIKE 'S%'

대부분의 프로그래머에게 뷰는 익숙하지만 인덱싱된 뷰는 생소할 수 있습니다. 인덱싱되지 않은 뷰의 뷰 데이터는 데이터베이스에 개별 복사본으로 저장되지 않으므로 뷰를 사용할 때마다 기본 제공 쿼리가 실행됩니다. 따라서 위의 예에서는 행 집합 WestCoastAuthors를 가져오는 쿼리가 실행되며 이 쿼리에는 필요한 특정 WestCoastAuthors를 끌어오는 술어가 포함됩니다. 인덱싱된 뷰는 데이터의 복사본을 저장하므로 WestCoastAuthors를 인덱싱된 뷰로 만들면 이들 작성자의 데이터 복사본을 두 개씩 얻게 됩니다. 이제 인덱싱된 뷰 또는 원본 테이블 중 하나를 경로로 선택하여 데이터를 업데이트할 수 있습니다. 그에 따라 SQL Server는 두 물리적 데이터 저장소에서 모두 변경 내용을 탐지한 후 다른 데이터 저장소에 이를 적용해야 합니다. 이러한 변경 탐지 메커니즘은 쿼리 알림이 설정되어 있을 때 엔진에서 사용하는 메커니즘과 동일합니다.

변경 탐지 특유의 구현 방식으로 인해 모든 뷰를 인덱싱할 수는 없습니다. 인덱싱된 뷰에 적용되는 이러한 제한 사항은 쿼리 알림에 사용되는 쿼리에도 적용됩니다. 예를 들어 WestCoastAuthors 뷰의 경우 뷰가 작성된 방식으로 인덱싱할 수는 없습니다. 이 뷰를 인덱싱하려면 뷰 정의에 두 부분으로 구성된 이름을 사용하고 모든 행 집합 열 이름을 명시적으로 지정해야 합니다. 그러면 이제 뷰를 변경하여 인덱싱을 수행해 보겠습니다.

CREATE VIEW WestCoastAuthors
WITH SCHEMABINDING
AS
SELECT au_id, au_lname, au_fname, address, city, state, zip, phone
  FROM dbo.authors
  WHERE state in ('CA', 'WA', 'OR')

여기서 인덱싱된 뷰 규칙을 따르는 쿼리만 알림과 함께 사용할 수 있습니다. 쿼리 결과의 변경 여부를 확인하는 데도 동일한 메커니즘이 사용되지만 인덱싱된 뷰에서처럼 쿼리 알림으로 인해 SQL Server에 데이터의 복사본이 생성되지는 않습니다. 인덱싱된 뷰에 대한 규칙 목록은 상당히 방대하며 SQL Server 2005 온라인 설명서에서 확인할 수 있습니다. 쿼리가 알림 요청과 함께 전송되고 규칙을 따르지 않는 경우 SQL Server는 즉시 "유효하지 않은 쿼리입니다"라는 알림을 이유와 함께 게시합니다. 그렇다면 알림은 "어디에 게시"될까요?

SQL Server 2005에서는 Service Broker 기능을 사용하여 알림을 게시합니다. Service Broker는 SQL Server에 기본 제공되는 비동기 대기열 기능이며, 쿼리 알림은 이 Service Broker 서비스를 사용합니다. 이 경우 서비스는 비동기 메시지의 대상이며 메시지는 계약이라는 일련의 특정 규칙을 따라야 합니다. Service Broker 서비스는 항상 물리적 메시지 대상인 대기열과 관련되어 있습니다. 쿼리 알림에 대한 계약은 SQL Server에 기본적으로 제공되며 이름은 http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification입니다.

참고   SQL Server의 계약 개체 이름은 URL이지만 위치를 나타내지 않습니다. 다시 말해 테이블 이름인 dbo.authors처럼 개체 이름에 불과합니다.

여기까지 종합해 보면 쿼리 알림 메시지의 대상은 적절한 계약을 지원하는 서비스라는 점을 알 수 있습니다. 서비스 등을 정의하는 SQL DDL은 다음과 같습니다.

CREATE QUEUE mynotificationqueue
CREATE SERVICE myservice ON QUEUE mynotificationqueue
 ([http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification])
GO

이제 쿼리 알림 요청에서 myservice 서비스를 대상으로 사용할 수 있을 것입니다. SQL Server는 서비스에 메시지를 보내는 방식으로 알림을 전송합니다. 고유한 서비스를 사용하거나 SQL Server에서 MSDB 데이터베이스의 기본 제공 서비스를 사용하도록 할 수도 있습니다. 고유한 서비스를 사용하는 경우에는 메시지를 읽고 처리하는 코드를 작성해야 합니다. 하지만 MSDB에 기본 제공되는 서비스를 사용하는 경우에는 메시지를 배달하는 미리 작성된 코드가 제공됩니다. 이 부분에 대해서는 나중에 다시 설명하겠습니다.

쿼리 알림에서 Service Broker를 사용하기 때문에 몇 가지 추가 요구 사항이 적용됩니다.

  1. Service Broker는 쿼리 알림을 실행하는 데이터베이스에서 활성화해야 합니다. 베타 2의 경우 AdventureWorks 샘플 데이터베이스에는 Service Broker가 기본적으로 활성화되어 있지 않지만, "ALTER DATABASE SET ENABLE_BROKER" DDL 문을 사용하여 활성화할 수 있습니다.
  2. 쿼리를 전송하는 사용자는 쿼리 알림을 구독할 수 있는 권한을 가지고 있어야 합니다. 쿼리 알림 구독은 데이터베이스마다 수행합니다. 다음 DDL을 실행하면 사용자에게 현재 데이터베이스에서 구독을 수행할 수 있는 'bob' 권한이 부여됩니다.
          GRANT SUBSCRIBE QUERY NOTIFICATIONS TO bob
    

최종 사용자 또는 캐시로 알림 발송

지금까지 알림 요청과 함께 올바른 쿼리 일괄 처리를 SQL Server로 전송했습니다. SQL Server는 행 집합을 감시하며 누군가 행 집합을 변경하면 선택한 서비스로 메시지가 전송됩니다. 그렇다면 이제 무엇을 해야 할까요? 먼저, 메시지를 읽고 알림이 발생할 때 필요한 모든 로직을 수행하는 사용자 지정 코드를 작성합니다. 아니면 기본 제공되는 발송자에서 이를 자동으로 수행하도록 할 수도 있습니다. 그러면 발송자에 대해 한번 살펴보겠습니다.

사용자 지정 서비스를 지정하지 않으면 쿼리 알림은 http://schemas.microsoft.com/SQL/Notifications/QueryNotificationService라는 MSDB 데이터베이스의 기본 서비스를 사용합니다.서비스 대기열에 메시지가 도착하면 sp_DispatcherProc이라는 대기열과 관련된 저장 프로시저에서 메시지를 자동으로 처리합니다. 한 가지 흥미로운 점은 이 프로시저는 .NET으로 작성된 코드를 사용한다는 점으로, 쿼리 알림을 자동으로 배달하려면 SQL Server 2005 인스턴스에 .NET CLR(공용 언어 런타임)을 로드하는 기능이 활성화되어 있어야 합니다. .NET CLR의 로드는 SQL Server 인스턴스별로 활성화하거나 비활성화할 수 있습니다.

쿼리 알림 메시지가 도착하면 sp_DispatcherProc(이하 "발송자")은 SqlDependency 알림 대기열의 쿼리 알림 구독 목록을 검색하여 각 구독자에게 메시지를 보냅니다. 서버는 발송자를 사용하여 데이터가 변경된 사실을 클라이언트에 알립니다. 이렇게 되면 클라이언트가 알림에 대해 폴링할 필요가 없을 뿐 아니라 알림을 수신하기 위해 SQL Server에 대한 연결을 열어 놓을 필요가 없기 때문에 매우 유용합니다. 발송자는 HTTP 프로토콜/TCP 및 개인 프로토콜을 사용하여 이 알림을 각 구독자에게 보냅니다. 서버와 클라이언트 간 통신은 선택적으로 인증할 수 있습니다. 알림이 배달되고 나면 활성 구독 목록에서 구독이 삭제됩니다. 클라이언트 구독별로 알림을 하나씩만 받으므로 쿼리를 다시 전송하고 다시 구독하는 일은 클라이언트에서 담당합니다.

데이터베이스 클라이언트에서 쿼리 알림 사용

지금까지 내부 작업을 모두 살펴보았으니 이제 이를 사용하는 ADO.NET 클라이언트를 작성해 보겠습니다. 어째서 비교적 간단한 클라이언트측 코드를 작성하면서 이처럼 많은 설명이 필요했을까요? 코드는 상당히 쉽게 작성할 수 있지만 반드시 규칙을 따라야만 합니다. 가장 일반적으로 발생하는 문제는 알림에 대해 유효하지 않은 쿼리를 전송한 다음 Service Broker와 사용자 권한을 설정하는 과정을 잊어버리는 경우입니다. 이로 인해 이처럼 강력한 기능이 애물단지로 전락하게 되었을 뿐 아니라, 일부 베타 테스터는 기능이 제대로 작동하지 않는다는 생각까지 하게 되었습니다. 따라서 간단한 예비 작업과 조사를 수행하면 많은 도움이 됩니다. 마지막으로 발송자에 대해 Service Broker 서비스 같은 속성과 프로토콜을 지정하게 되므로 먼저 내부 작업을 수행하는 편이 유익합니다. 이제는 이러한 용어들이 어떤 의미인지 알게 되었을 것입니다.

ADO.NET에서 쿼리 알림 클라이언트를 작성할 수 있는 것처럼 여기서는 OLE DB나 새로운 HTTP 웹 서비스 클라이언트를 사용하여 이를 작성할 예정입니다. 하지만 유의해야 할 부분은 쿼리 알림은 클라이언트측 코드를 통해서만 사용할 수 있는 점입니다. 이 기능을 T-SQL과 바로 함께 사용하거나 SqlServer 데이터 공급자를 사용하여 SQL Server와 통신하는 SQLCLR 프로시저 코드와 함께 사용할 수는 없습니다.

System.Data.dll 어셈블리에는 SqlDependencySqlNotificationRequest라는 두 개의 클래스가 들어 있습니다. SqlDependency는 발송자를 사용하여 자동 알림을 실행하려는 경우 사용합니다. SqlNotificationRequest는 알림 메시지를 직접 처리하려는 경우에 사용합니다. 그럼, 지금부터 이들 클래스의 예제를 살펴보겠습니다.

SqlDependency 사용

SqlDependency의 사용 단계는 간단합니다. 먼저, 쿼리 알림을 수행해야 하는 SQL 문이 들어 있는 SqlCommand를 만들고, SqlCommandSqlDependency를 연결합니다. 그런 다음 SqlDependency OnChanged 이벤트에 대해 이벤트 처리기를 등록합니다. 그런 다음 SqlCommand를 실행합니다. DataReader를 처리하고 닫는 것은 물론 연관된 SqlConnection까지 닫을 수 있습니다. 이제 행 집합이 변경되면 발송자를 통해 알림을 수신하게 됩니다. 이 개체에 대한 이벤트는 서로 다른 스레드에서 발생합니다. 따라서 코드 실행 중에 이벤트가 발생하는 상황을 처리할 수 있도록 대비해야 합니다. 경우에 따라 이벤트가 발생하는 상황에 일괄 처리 결과를 계속 처리할 수도 있습니다. 코드는 다음과 같습니다.

using System;
using System.Data;
using System.Data.SqlClient;
static void Main(string[] args)
{
  string connstring = GetConnectionStringFromConfig();
  using (SqlConnection conn = new SqlConnection(connstring))
  using (SqlCommand cmd = 
   // 2-part table names, no "SELECT * FROM ..."
   new SqlCommand("SELECT au_id, au_lname FROM dbo.authors", conn))
 {
  try
  {
    // cmd와 연관된 종속성을 만듭니다.
    SqlDependency depend = new SqlDependency(cmd);
    // 처리기를 등록합니다.
    depend.OnChanged += new OnChangedEventHandler(MyOnChanged);
    conn.Open();
    SqlDataReader rdr = cmd.ExecuteReader();
    // DataReader를 처리합니다.
    while (rdr.Read())
    Console.WriteLine(rdr[0]);
    rdr.Close();
    // 무효화가 완료될 때까지 기다립니다.
    Console.WriteLine("Press Enter to continue");
    Console.ReadLine();
  }
  catch (Exception e)
   { Console.WriteLine(e.Message); }
 }
}
static void MyOnChanged(object caller, SqlNotificationEventArgs e)
{
  Console.WriteLine("result has changed");
  Console.WriteLine("Source " + e.Source);
  Console.WriteLine("Type " + e.Type);
  Console.WriteLine("Info " + e.Info);(참고: 프로그래머 코멘트는 샘플 프로그램 파일에는 영문으로 제공되며 기사에는 설명을 위해 번역문으로 제공됩니다.)
}

Visual Basic .NET에서 친숙한 WithEvents 키워드와 SqlDependency를 함께 사용해도 이와 동일한 코드를 작성할 수 있습니다. 이 프로그램은 기본 결과의 변경 횟수에 관계없이 OnChanged 이벤트를 한 번만 가져와 처리합니다. 실제 사용 시 알림을 받았을 때 해야 할 일은 새로운 알림과 함께 명령을 다시 전송하고 그 결과를 바탕으로 캐시를 새 데이터로 새로 고치는 것입니다. 위 예제의 Main()에 여기서 작성한 코드를 가져와 명명된 루틴으로 이동하면 코드의 형태는 다음과 같습니다.

static void Main(string[] args)
{
    GetAndProcessData(); 
    UpdateCache();
    // 사용자가 프로그램을 종료할 때까지 기다립니다.
    Console.WriteLine("Press Enter to continue");
    Console.ReadLine();
}
static void MyOnChanged(object caller, SqlNotificationEventArgs e)
{
    GetAndProcessData(); 
    UpdateCache();
}

일부 단락을 보면 이것이 ASP.NET Cache 클래스를 데이터 캐시로 사용하여 ASP.NET 2.0를 실행하는 것과 완전히 똑같다는 사실을 알 수 있습니다.

SqlDependency를 사용하는 경우에는 SQL Server 2005의 발송자 구성 요소를 통해 클라이언트에 연결하고 알림 메시지를 보냅니다. 이는 SqlConnection을 사용하지 않는 대역 외 통신입니다. 이는 또한 클라이언트가 SQL Server를 통해 "네트워크를 사용할 수 있어야"하며 방화벽 및 네트워크 주소 변환으로 인해 문제가 발생할 수 있다는 것을 의미합니다. 향후 베타 버전이 출시되면 포트 구성에 대한 제어 성능이 강화되어 방화벽을 보다 자유롭게 사용할 수 있을 것입니다. SqlDependency 생성자에 매개 변수를 지정하여 서버와 클라이언트가 통신하는 방식을 완벽하게 구성할 수 있습니다. 다음은 이에 대한 예제입니다.

SqlDependency depend = new SqlDependency(cmd,
    null,
    SqlNotificationAuthType.None,
    SqlNotificationEncryptionType.None,
    SqlNotificationTransports.Tcp,
    10000);

SqlDependency 생성자를 사용하면 기본값 대신 다양한 동작을 선택할 수 있습니다. 변경할 동작 중 가장 유용한 것은 서버에서 클라이언트와 연결하는 데 사용하는 유선 전송입니다. 이 예제에서는 SqlNotificationTransports.Tcp를 사용하므로 서버에서는 TCP 또는 HTTP를 사용할 수 있습니다. 이 매개 변수의 기본값은 SqlNotificationTransports.Any이며, 서버에서는 이를 통해 사용할 전송을 "결정"할 수 있습니다. Any가 지정된 경우 서버는 클라이언트 운영 체제에 커널 모드 HTTP 지원이 포함된 경우에는 HTTP를 선택하고, 그렇지 않은 경우에는 TCP를 선택하게 됩니다. Windows Server 2003 및 Windows XP(SP2)에는 커널 모드 HTTP 지원이 포함되어 있습니다. 또한 네트워크를 통해 메시지를 보내기 때문에 사용할 인증 형식을 지정할 수 있습니다. EncryptionType은 현재 매개 변수로 사용되고 있지만 이후 베타 버전에서는 제거될 예정입니다. 현재 두 값 모두에 대한 기본값은 None입니다. SqlNotificationAuthType은 통합 인증도 지원합니다. 또한 구독에 대한 시간 제한 값과 SQL Server Service Broker 서비스의 이름을 명시적으로 지정할 수 있습니다. 서비스 이름은 예제에서처럼 대개 null로 설정되지만 기본 제공 서비스인 SqlQueryNotificationService를 명시적으로 지정할 수도 있습니다. 대개 다시 정의할 확률이 가장 높은 매개 변수는 SqlNotificationTransport와 시간 제한입니다. 이러한 매개 변수는 서버측 발송자의 동작을 지정하므로 SqlDependency에만 적용할 수 있습니다. SqlNotificationRequest를 사용하는 경우에는 발송자를 사용하지 않습니다.

SqlNotificationRequest 사용

SqlNotificationRequest를 사용하려면 SqlDependency보다 약간 복잡한 설정 과정을 거쳐야 하지만 메시지 처리는 프로그램에서 담당하게 됩니다. SqlDependency를 사용하면 서버의 알림이 MSDB의 SqlQueryNotificationService로 전송되어 메시지가 자동으로 처리됩니다. 하지만 SqlNotificationRequest를 사용하는 경우에는 메시지를 직접 처리해야 합니다. 다음은 SqlNotificationRequest와 이 기사의 앞부분에서 정의한 서비스를 사용하는 간단한 예제입니다.

using System;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;
class Class1
{
  string connstring = null;
  SqlConnection conn = null;
  SqlDataReader rdr = null;
  static void Main(string[] args)
  {
    connstring = GetConnectionStringFromConfig();
    conn = new SqlConnection(connstring));
    Class1 c = new Class1();
    c.DoWork();  
  }
  void DoWork()
  {
    conn.Open();
    rdr = GetJobs(2);
    if (rdr != null)
    {
      rdr.Close();
      WaitForChanges();
    }
    conn.Dispose();
  }
  public SqlDataReader GetJobs(int JobId)
  {
    using (SqlCommand cmd = new SqlCommand(
        "Select job_id, job_desc from dbo. jobs where job_id = @id",
        conn))
    {
      
    try
    {
      cmd.Parameters.AddWithValue("@id", JobId);
      SqlNotificationRequest not = new SqlNotificationRequest();
      not.Id = new Guid();
      // 이것은 notificationqueue라는 대기열과 연관된 pubs 데이터베이스의
      // MyService라는 서비스여야 합니다(아래 참조).
      // 서비스는 QueryNotifications 계약에 따라야 합니다.
      not.Service = "myservice";
      not.Timeout = 0; 
      // 알림 요청을 연결합니다.
      cmd.Notification = not;
      rdr = cmd.ExecuteReader();
      while (rdr.Read())
     Console.WriteLine(rdr[0]);
     rdr.Close();
    }
    catch (Exception ex)
    { Console.WriteLine(ex.Message); }
    return rdr;
    }
  }
  public void WaitForChanges()
  {
    // 알림이 대기열에 나타날 때까지
    // 기다렸다가 직접 읽고 확인합니다.
    using (SqlCommand cmd = new SqlCommand(
     "WAITFOR (Receive convert(xml,message_body) from notificationqueue)",    
      conn))
    {
      object o = cmd.ExecuteScalar();
      // 필요에 따라 알림 메시지를 처리합니다.
      Console.WriteLine(o); 
    }
  }

SqlNotificationRequest를 사용하는 장점(추가 작업이기도 함)은 알림을 기다렸다가 직접 처리해야 한다는 점입니다. SqlDependency를 사용하는 경우에는 알림을 수신하기 전까지 데이터베이스에 다시 연결할 필요가 없습니다. SqlNotificationRequest 알림은 기다릴 필요가 없으며 대기열만 가끔씩 폴링하면 됩니다. SqlNotificationRequest의 또 다른 사용 예로는 알림이 발생하면 실행조차 되지 않은 특수한 응용 프로그램을 작성하는 경우입니다. 응용 프로그램이 시작되면 대기열에 연결되어 이전 응용 프로그램 실행의 "영구 캐시" 결과가 더 이상 유효하지 않음을 확인할 수 있습니다.

알림을 몇 시간 또는 몇 일 동안 기다릴 수 있는 응용 프로그램에 대해 설명하다 보면, "데이터가 변경되지 않으면 알림은 언제 사라집니까?"와 같은 질문을 받게 됩니다. 데이터베이스의 구독 테이블에서 삭제되는 것처럼 알림을 사라지게 하는 유일한 요인은 알림이 발생되거나 알림이 만료되는 경우뿐입니다. 알림 구독이 SQL 리소스를 사용하고 쿼리 및 업데이트에 오버헤드를 추가하기 때문에 이를 기다리는 일이 귀찮은 데이터베이스 관리자는 SQL Server에서 알림을 수동으로 삭제할 수도 있습니다. 먼저 SQL Server 2005 동적 뷰에 대해 알림을 쿼리하고 성가신 알림 구독을 검색한 다음 명령을 실행하여 제거하면 됩니다.

  -- 모든 구독을 찾습니다.
  SELECT * FROM sys.dm_qn_subscriptions
  -- 원하는 구독의 ID를 선택한 다음
  -- ID = 42인 구독을 삭제합니다.
  KILL QUERY NOTIFICATION SUBSCRIPTION 42

ASP.NET에서 SqlCacheDependency 사용

ASP.NET Cache 클래스에도 알림을 연결할 수 있습니다. ASP.NET 2.0에서는 CacheDependency 클래스를 하위 클래스로 지정할 수 있으며, SqlCacheDependencySqlDependency를 캡슐화하고 다른 ASP.NET CacheDependency와 마찬가지로 작동합니다. SqlCacheDependency는 사용하는 버전이 SQL Server 2005이든, 이전 버전의 SQL Server든 관계없이 작동하므로 SqlDependency보다 효율성이 뛰어납니다. 물론 SQL Server 2005 이전 버전에서는 완전히 다른 방식으로 구현되어 있습니다.

이전 버전의 SQL Server를 사용하는 경우에는 "감시"할 테이블의 트리거를 사용하는 방식으로 SqlCacheDependency가 작동하게 됩니다. 이러한 트리거는 다른 SQL Server 테이블에 행을 쓰는 역할을 하며, 그러면 이 테이블이 폴링됩니다. 어떤 테이블의 종속성 및 폴링 간격 값을 활성화할지도 구성할 수 있습니다. SQL Server 2005 이전 구현에 대한 자세한 설명은 이 기사의 범위를 벗어나므로 자세한 내용은 Improved Caching in ASP.NET 2.0(영문)을 참조하십시오.

SQL Server 2005를 사용하는 경우 위의 ADO.NET 예제와 유사하게 SqlCacheDependency에서 SqlDependency 인스턴스를 캡슐화합니다. 다음은 SqlCacheDependency를 사용하는 간단한 코드 예제입니다.

// Page.Load를 호출했습니다.
CreateSqlCacheDependency(SqlCommand cmd)
{
  SqlCacheDependency dep = new SqlCacheDepedency(cmd);
  Response.Cache.SetExpires(DateTime.Now.AddSeconds(60);
  Response.Cache.SetCacheability(HttpCacheability.Public);
  Response.Cache.SetValidUntilExpires(true);
  Response.AddCacheDependency(dep);
}

사용이 편리한 뛰어난 기능 한 가지는 SqlCacheDependency가 페이지 또는 페이지 조각 캐시에도 연결된다는 점입니다. 또한 특정 ASP.NET OutputCache 지시문에서 모든 SqlCommands를 선언적으로 활성화할 수 있습니다. 여기에서는 페이지의 모든 SqlCommands에 대해 동일한 SqlDependency가 사용되며, SQL Server 2005 데이터베이스에 사용되는 형태와 유사합니다.

<%OutputCache SqlDependency="CommandNotification" ... %>

CommandNotification은 "SQL Server 2005 및 SqlDependency를 사용한다"는 의미의 키워드 값입니다. 이전 버전의 SQL Server를 사용하는 경우에는 이 지시문 매개 변수의 구문이 완전히 다릅니다. 또한 특정 운영 체제 버전에서 ASP.NET 2.0을 실행하면 CommandNotification 키워드 값만 활성화됩니다.

향상된 알림 기능

SQL Server 쿼리 알림의 디자인 정책은 클라이언트에 대해 알림을 빠뜨리는 것보다는 지나칠 정도로 자주 보내는 게 낫다는 것을 골자로 하고 있습니다. 대개 다른 누군가 행을 변경하여 캐시가 무효화되면 알림을 받게 되지만 항상 그런 것은 아닙니다. 예를 들어 DBA가 데이터베이스를 재활용하면 알림을 받게 됩니다. 또한 쿼리의 테이블 중 하나라도 변경되거나 삭제되거나 잘려도 알림을 받습니다. 쿼리 알림은 SQL Server 리소스를 소비하므로 SQL Server 리소스의 스트레스가 심각해지면 내부 테이블에서 쿼리 알림을 제거하기 시작할 수 있으며 이런 경우에도 클라이언트에서 알림을 받게 됩니다. 또한 각 알림 요청에는 시간 제한 값이 들어 있으므로 구독 제한 시간이 초과되면 알림을 수신합니다.

SqlDependency를 사용하는 경우 발송자는 SqlNotificationEventArgs 인스턴스에 이 정보를 요약합니다. 이 클래스에는 Info, Source 및 Type의 세 가지 속성이 포함되어 있으며, 이를 통해 알림을 유발하는 부분을 지정할 수 있습니다. SqlNotificationRequest를 사용하는 경우 대기열 메시지의 message_body 필드에 이와 동일한 정보가 포함된 XML 문서가 있지만 XPath 또는 XQuery를 사용하여 직접 구문 분석해야 합니다. 다음은 앞의 ADO.NET SqlNotificationRequest 예제에서 만든 샘플 XML 문서입니다.

<qn:QueryNotification 
 xmlns:qn="http://schemas.microsoft.com/SQL/Notifications/QueryNotification" 
 id="2" type="change" source="data" info="update" 
 database_id="6" user_id="1">
<qn:Message>{CFD53DDB-A633-4490-95A8-8E837D771707}</qn:Message>
</qn:QueryNotification>

필자는 job_id = 5인 행에서 job_desc 열 값을 "new job"으로 변경하여 이 알림을 만들었지만 message_body에는 이 정보가 표시되지 않습니다. 이를 통해 알림 프로세스의 마지막 몇 가지 차이점을 확인할 수 있습니다. 알림의 기능은 SQL 문을 통해 어떤 항목이 변경되어 행 집합이 변경될 수 있음을 인식하는 정도에 그친다는 사실입니다. 알림 기능으로는 UPDATE 문이 행의 실제 값을 변경하지 않는 경우까지는 인식하지 못합니다. 예를 들어, 행을 job_desc = "new job"에서 job_desc = "new job"으로 변경하면 알림이 생성됩니다. 또한 쿼리 알림은 비동기적으로 수행되며 명령 또는 일괄 처리를 실행할 때 등록되므로 행 집합 읽기를 마치기 전에 알림을 받을 수 있습니다. 규칙을 따르지 않는 쿼리를 전송하는 경우에도 즉시 알림을 받을 수 있습니다. 여기서 규칙은 앞에서 언급한 인덱싱된 뷰에 대한 규칙입니다.

알림을 사용하지 않는 경우: 교훈

이제 쿼리 알림이 작동하는 방식을 이해했으므로 이를 어디에 사용해야 할지 명백해졌습니다. 바로 읽기 위주 조회 테이블입니다. 각 알림 행 집합은 SQL Server의 리소스를 처리하므로 이를 읽기 전용 테이블에 사용하는 것은 여러모로 쓸데없는 낭비입니다. 또한 동시에 "감시"하는 서로 다른 행 집합 수만 지나치게 많아질 뿐이므로 임시 쿼리에도 사용할 필요가 없습니다. 유용한 내부 작업 관련 정보 한 가지는 SQL Server는 서로 다른 매개 변수 집합을 사용하는 매개 변수가 지정된 쿼리에 대해 알림 리소스를 끌어온다는 사실입니다. 위 예제의 SqlNotificationRequest에서처럼 매개 변수가 지정된 쿼리를 사용하면 항상 이러한 이점을 얻는 것은 물론 성능을 높일 수도 있습니다. 이 이야기를 듣고 염려할 수도 있겠지만 이처럼 강력한 기능을 사용한다고 해서 적절한 알림을 받지 않는 것은 아닙니다. user1이 A-M에서 au_lname인 제작자를 감시하고 user2가 au_lname 값을 매개 변수로 사용하여 N-Z에서 au_lname을 감시하는 경우 각 사용자는 각 하위 집합에 "해당하는" 알림만 받게 됩니다.

마지막으로 한 가지 주의할 점은 어떤 사람은 알림 응용 프로그램을 떠올릴 때 시장 가격이 변화하고 화면이 끊임없이 바뀌며 주식 거래자들로 가득 찬 공간을 상상한다는 점입니다. 이는 이 기능을 명백히 잘못 사용하는 것이며 그 이유는 다음과 같은 두 가지로 볼 수 있습니다.

  1. 행 집합은 계속해서 변하므로 네트워크는 쿼리 알림과 쿼리 새로 고침 요청으로 넘쳐 날 수 있습니다.
  2. 몇 명 이상의 사용자가 모두 같은 데이터를 "감시"하는 경우 각각의 알림으로 인해 많은 사용자가 동일한 결과에 대해 동시에 다시 쿼리하는 상황이 발생합니다. 이렇게 되면 SQL Server는 동일한 데이터에 대한 지나치게 많은 요청으로 넘치게 될 수 있습니다.

프로그래머가 이 기능을 잘못 사용할 수 있다고 생각되더라도 베타 2 이후의 SQL Server에서는 DBA가 동적 관리 뷰를 통해 이러한 기능을 모니터링할 수 있도록 하는 자세한 정보를 제공하므로 안심해도 됩니다. 현재 이들 뷰에서는 구독만 표시할 수 있습니다. SQL Server 2005에서는 항상 알림이 과도한 양의 리소스를 가져와 이를 제거하도록 "결정"할 수 있음을 기억하시기 바랍니다.

결론

쿼리 알림은 SQL Server 2005에 기본적으로 제공되는 강력하고 새로운 기능으로, ADO.NET 2.0과 ASP.NET 2.0에서 바로 사용할 수 있습니다. ADO.NET 기능(SqlNotificationRequestSqlDependency)은 SQL Server 2005 데이터베이스에 대해서만 작동하지만, ASP.NET에서는 폴링을 사용하는 대체 메커니즘을 통해 이 기능을 "이전 버전과도 호환하여" 사용할 수 있습니다. 이 기능은 구문 및 관련된 영향을 염두에 두고 신중하게 사용해야 합니다. 특히 이 기능의 핵심 부분은 ASP.NET에서 사용되는 읽기 위주 테이블입니다. 이러한 테이블은 다른 응용 프로그램은 물론 웹 응용 프로그램에서도 업데이트할 수 있습니다. 이 시나리오에서 쿼리 알림은 프로그래머들이 수년간 기다려 온 솔루션을 제공하고 있습니다.


,
STUDY/SQL Cache Dependency 2007. 4. 26. 15:04

[Study] SqlCacheDependency using DAAB and SQL Server 2005 - Enterprise Library 2.0

SqlCacheDependency using DAAB and SQL Server 2005 - Enterprise Library 2.0

SqlCacheDependency using DAAB and SQL Server 2005

by David Hayden ( .NET Developer )

 

I didn't think to include this in my previous post, SqlCacheDependency using ASP.NET 2.0 and SQL Server 2005, but with only a few minor changes you can use the Enterprise Library 2.0 DAAB with SqlCacheDependency and SQL Server 2005. For completeness I will include all the previous information, but the only code that changes is the code to create the command object and get the DataSet. The code is reduced by about 5 or 6 lines and there is no concern of connection management.

Here is now the previous article using the Enterprise Library 2.0 DAAB instead of SqlClient, except for the fact that we need to cast DbCommand to SqlCommand for use in the constructor of the SqlCacheDependency object.

 

SqlCacheDependency using ASP.NET 2.0 and SQL Server 2005 is a beautiful thing :) Although getting SqlCacheDependency to work with SQL Server 2000 is not rocket science, there are a few extra moving parts that need to be set-up in your web.config and on SQL Server 2000. When using SQL Server 2005, all of that goes away :)

 

Enable Service Broker

Before SqlCacheDependency will work with SQL Server 2005, you first have to enable Service Broker, which is reponsible for the notification services that let the web cache know a change has been made to the underlying database and that the item in the cache must be removed.


ALTER DATABASE Store SET ENABLE_BROKER;
GO

SqlCacheDependency.Start() in Global.asax

In ASP.NET, you need to run SqlCacheDependency.Start(connectionString) in the Global.asax:


void Application_Start(object sender, EventArgs e) 
{
    string connectionString = WebConfigurationManager.
        ConnectionStrings["Catalog"].ConnectionString;
    SqlDependency.Start(connectionString);
}

SqlCacheDependency in ASP.NET 2.0 Example

Now you can just create your SqlCacheDependency as normal in your ASP.NET 2.0 page. Here is a simple example:


public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        DataTable categories = (DataTable)Cache.Get("Categories");

        if (categories == null)
        {
            categories = GetCategories();
            Label1.Text = System.DateTime.Now.ToString();
        }

        GridView1.DataSource = categories.DefaultView;
        GridView1.DataBind();
    }

    private DataTable GetCategories()
    {
        Database db = DatabaseFactory.CreateDatabase();

        SqlCommand command = (SqlCommand)db.
GetSqlStringCommand(
"SELECT CategoryID,Code,
Title FROM dbo.Categories
"); SqlCacheDependency dependency =
new SqlCacheDependency(command); DataSet dataset = db.ExecuteDataSet(command); DataTable categories = dataset.Tables[0]; Cache.Insert("Categories", categories, dependency); return categories;
} }

Since I am using a normal SELECT statement above, there are a number of rules one needs to follow, such as

  • You cannot use SELECT * - use individual fields
  • Must use fully qualified name of table, e.g. dbo.Categories

and a whole bunch of other rules outlined here on MSDN.

There are other ways to use SqlCacheDependency as well, such as with Ouput Caching. I can show those at another time.

Source: David Hayden ( .NET Developer )

Filed: ASP.NET 2.0, SQL Server 2005, Enterprise Library 2.0


posted on Sunday, April 30, 2006 4:09 PM

,
TOTAL TODAY