데이터 소스 컨트롤은 Microsoft Visual Studio 2005에 도입된 새로운 유형의 서버 컨트롤입니다. 이는 데이터 바인딩 아키텍처의 핵심 부분이며 데이터 바인딩 컨트롤을 통해 선언적 프로그래밍 모델과 자동 데이터 바인딩 동작을 제공할 수 있습니다. 이 문서와 이 시리즈의 후속 문서에서는 데이터 소스 컨트롤 구현의 핵심 요소를 소개합니다.
소개
간단히 말해서, 데이터 소스 컨트롤은 데이터 저장소와 포함된 데이터에 대해 수행할 수 있는 일부 작업을 요약합니다. DataBound 컨트롤은 DataSourceID 속성을 통해 데이터 소스 컨트롤과 연결됩니다. 대부분의 기존 데이터 저장소는 테이블 형식이거나 계층적이며 데이터 원본 제어는 그에 따라 구분됩니다. 여기서 소개하고 싶은 것은 테이블 형식의 데이터 소스 컨트롤입니다.
데이터 소스 컨트롤 자체는 많은 작업을 수행하지 않습니다. 모든 논리는 DataSourceView 파생 클래스에 캡슐화됩니다. 최소한 하나의 DataSourceView는 행 집합을 검색(즉, 선택)하는 기능을 구현해야 합니다. 데이터 수정(예: INSERT, UPDATE 및 DELETE) 기능을 제공할 수 있습니다(선택 사항). 데이터 바인딩된 컨트롤은 다양한 Can??? 속성을 통해 활성화된 기능 세트를 확인할 수 있습니다. 데이터 소스 컨트롤 자체는 고유하게 명명된 하나 이상의 뷰에 대한 컨테이너일 뿐입니다. 관례적으로 기본 보기는 해당 이름으로 액세스할 수 있거나 비어 있을 수 있습니다. 서로 다른 뷰 사이에 어떤 관계가 존재하는지 여부는 각 데이터 소스 컨트롤의 구현에 따라 적절하게 정의될 수 있습니다. 예를 들어 데이터 소스 컨트롤은 서로 다른 보기를 통해 동일한 데이터에 대해 서로 다른 필터링된 보기를 제공하거나 보조 보기에 하위 행 집합을 제공할 수 있습니다. 데이터 바인딩된 컨트롤의 DataMember 속성을 사용하여 특정 뷰를 선택할 수 있습니다(데이터 소스 컨트롤이 여러 뷰를 제공하는 경우). 현재 Whidbey에 내장된 데이터 소스 컨트롤 중 어느 것도 다중 보기를 제공하지 않습니다.
마지막으로 몇 가지 콘텐츠를 소개하겠습니다. 데이터 소스 컨트롤(및 해당 뷰)은 두 가지 API 세트를 구현합니다. 첫 번째 API 세트는 데이터 바인딩된 컨트롤에서 일반적인 방식으로 사용할 수 있는 네 가지 일반적인 데이터 작업에 대해 정의된 추상 인터페이스입니다. 두 번째 그룹은 선택 사항이며, 해당 그룹이 나타내는 도메인 또는 데이터 저장소 측면에서 정의되고 일반적으로 강력한 형식이며 응용 프로그램 개발자를 위한 것입니다.
예제
이 기사에서는 우편번호를 기준으로 날씨 정보를 검색하기 위해 Weather.com(영어)에서 제공하는 REST(영어) XML API에 대해 작동하는 WeatherDataSource를 구현합니다. 일반적으로 파생 데이터 소스 컨트롤이 먼저 구현됩니다.
공개 클래스 WeatherDataSource : DataSourceControl {
공개 정적 읽기 전용 문자열
CurrentConditionsViewName = "CurrentConditions";
WeatherDataSourceView
_currentConditionsView;
얻다 {
if (_currentConditionsView == null) {
_currentConditionsView = new WeatherDataSourceView(this, CurrentConditionsViewName);
}
_currentConditionsView를 반환합니다.
}
}
공개 문자열 우편번호 {
얻다 {
string s = (string)ViewState["ZipCode"];
반환(s != null) ?s: String.Empty;
}
세트 {
if (String.Compare(값, 우편번호,
StringComparison.Ordinal) != 0) {
ViewState["ZipCode"] = 값;
CurrentConditionsView.RaiseChangedEvent();
}
}
}
보호된 재정의 DataSourceView GetView(string viewName) {
if (String.IsNullOrEmpty(viewName) ||
(String.Compare(viewName, CurrentConditionsViewName,
StringComparison.OrdinalIgnoreCase) == 0)) {
CurrentConditionsView를 반환합니다.
}
새로운 ArgumentOutOfRangeException("viewName")을 던져라;
}
보호 재정의 ICollection GetViewNames() {
새로운 문자열을 반환[] { CurrentConditionsViewName };
}
공개 날씨 GetWeather() {
CurrentConditionView.GetWeather()를 반환합니다.
}
}
보시다시피 기본 아이디어는 GetView를 구현하여 명명된 뷰 인스턴스를 반환하고 GetViewNames를 구현하여 사용 가능한 뷰 집합을 반환하는 것입니다.
여기서는 DataSourceControl에서 파생을 선택합니다. 알아차리기 쉽지 않은 한 가지 사실은 데이터 바인딩된 컨트롤이 실제로 IDataSource 인터페이스를 찾고, DataSource 컨트롤이 GetView 및 GetViewNames를 구현하여 인터페이스를 구현한다는 것입니다. 인터페이스가 필요한 이유는 데이터 소스 컨트롤을 테이블 형식과 계층형으로 모두 가능하게 하기 위한 것입니다(가능한 경우 기본 모델에서 파생되고 다른 모델을 인터페이스로 구현함). 둘째, 다양한 시나리오에서 다른 컨트롤을 변환하여 데이터 소스의 용량을 두 배로 늘릴 수도 있습니다. 또한 강력한 형식의 Weather 개체를 반환하는 공개 ZipCode 속성과 GetWeather 메서드에 유의하세요. 이 API는 페이지 개발자에게 적합합니다. 페이지 개발자는 DataSourceControl 및 DataSourceView에 대해 생각할 필요가 없습니다.
다음 단계는 데이터 소스 뷰 자체를 구현하는 것입니다. 이 특정 예에서는 SELECT 수준 기능(최소 요구 사항이자 이 시나리오에서 유용한 유일한 기능)만 제공합니다.
비공개 봉인 클래스 WeatherDataSourceView : DataSourceView {
private WeatherDataSource _owner;
public WeatherDataSourceView(WeatherDataSource 소유자, 문자열 viewName)
: 베이스(소유자, 뷰이름) {
_소유자 = 소유자;
}
보호 재정의 IEnumerable ExecuteSelect(
DataSourceSelectArguments 인수) {
인수.RaiseUnsupportedCapabilityError(this);
날씨 WeatherObject = GetWeather();
return new Weather[] { WeatherObject };
}
내부 날씨 GetWeather() {
문자열 zipCode = _owner.ZipCode;
if (zipCode.Length == 0) {
새로운 InvalidOperationException()을 던져라;
}
WeatherService WeatherService = new WeatherService(zipCode);
WeatherService.GetWeather()를 반환합니다.
}
내부 무효 raiseChangedEvent() {
OnDataSourceViewChanged(EventArgs.Empty);
}
}
기본적으로 DataSourceView 클래스는 CanUpdate와 같은 속성에서 false를 반환하고 Update 및 관련 메서드에서 NotSupportedException을 발생시킵니다. WeatherDataSourceView에서 수행해야 할 유일한 작업은 추상 ExecuteSelect 메서드를 재정의하고 "선택된" 날씨 데이터가 포함된 IEnumerable을 반환하는 것입니다. 구현에서는 도우미 WeatherService 클래스가 사용됩니다. 이 클래스는 단순히 WebRequest 객체를 사용하여 선택한 우편번호를 사용하여 Weather.com(영어)을 쿼리합니다(특별한 것은 없음).
ExecuteSelect가 보호됨으로 표시되어 있음을 알 수 있습니다. 데이터 바인딩된 컨트롤이 실제로 호출하는 것은 콜백에 전달된 공개(및 봉인) Select 메서드입니다. Select 구현에서는 ExecuteSelect를 호출하고 결과 IEnumerable 인스턴스로 콜백을 호출합니다. 이 패턴은 매우 이상합니다. 이에 대한 이유는 이 시리즈의 후속 기사에서 설명될 것입니다. 잠시 기다려 주십시오...
다음은 이 사용법의 예입니다:
우편번호: <asp:TextBox runat="server" id="zipCodeTextBox" />
<asp:Button runat="server" onclick="OnLookupButtonClick" Text="Look" />
<hr />
<asp:FormView runat="server" DataSourceID="weatherDS">
<아이템템플릿>
<asp:레이블 runat="서버"
Text='<%# Eval("온도", "현재 온도는 {0}입니다.") %>' />
</아이템템플릿>
</asp:FormView>
<nk:WeatherDataSource runat="server" id="weatherDS" ZipCode="98052" />
<script runat="server">
private void OnLookupButtonClick(개체 전송자, EventArgs e) {
WeatherDS.ZipCode = zipCodeTextBox.Text.Trim();
}
</script>
이 코드는 사용자 입력에 대한 응답으로 우편번호를 설정합니다. 그러면 데이터 소스가 변경 알림을 발행하여 바인딩된 FormView 컨트롤이 데이터 바인딩을 수행하고 디스플레이를 변경하게 됩니다.
이제 데이터 액세스 코드가 데이터 소스 제어에 캡슐화됩니다. 또한 이 모델을 사용하면 Weather.com(영문)이 해당 서비스와 관련된 세부 정보를 캡슐화할 수 있는 구성 요소를 게시할 수 있습니다. 잘 작동할 것입니다. 또한 추상 데이터 소스 인터페이스를 통해 FormView는 날씨 데이터에 대해서만 작동할 수 있습니다.
다음 문서에서는 데이터를 쿼리하는 데 사용되는 필터 값(즉, 우편번호)에 대한 변경 사항을 자동으로 처리하도록 데이터 소스 제어를 향상시킵니다.