작성자: 스콧 미첼
Typed DataSet 내의 TableAdapters는 데이터베이스에 연결하고, 명령을 실행하고, DataTable을 결과로 채우는 작업을 자동으로 처리합니다. 그러나 이러한 세부 정보를 직접 처리하려는 경우가 있으며, 이 자습서에서는 TableAdapter의 데이터베이스 연결 및 명령 수준 설정에 액세스하는 방법을 알아봅니다.
소개
자습서 시리즈 전반에 걸쳐 Typed DataSets를 사용하여 계층화된 아키텍처의 데이터 액세스 계층 및 비즈니스 개체를 구현했습니다. 첫 번째 자습서에서 설명한 것처럼 Typed DataSet의 DataTable은 데이터의 리포지토리 역할을 하는 반면 TableAdapters는 기본 데이터를 검색하고 수정하기 위해 데이터베이스와 통신하는 래퍼 역할을 합니다. TableAdapters는 데이터베이스 작업과 관련된 복잡성을 캡슐화하고 데이터베이스에 연결하거나 명령을 실행하거나 결과를 DataTable로 채우는 코드를 작성할 필요가 없도록 합니다.
그러나 TableAdapter의 깊이로 잠복하고 ADO.NET 개체에서 직접 작동하는 코드를 작성해야 하는 경우가 있습니다. 예를 들어 트랜잭션 내에서 데이터베이스 수정을 래핑하기 튜토리얼에서는 ADO.NET 트랜잭션을 시작, 커밋 및 롤백하기 위해 TableAdapter에 메서드를 추가했습니다. 이러한 메서드는 TableAdapter SqlTransaction
의 개체에 할당된 수동으로 만든 SqlCommand
내부 개체를 사용했습니다.
이 자습서에서는 TableAdapter에서 데이터베이스 연결 및 명령 수준 설정에 액세스하는 방법을 살펴봅니다. 특히 기본 연결 문자열 및 명령 시간 제한 설정에 액세스할 수 있도록 하는 기능을 ProductsTableAdapter
추가합니다.
ADO.NET 사용하여 데이터 작업
Microsoft .NET Framework에는 데이터 작업을 위해 특별히 설계된 다양한 클래스가 포함되어 있습니다.
네임스페이스 내에 있는 이러한 클래스를System.Data
ADO.NET 클래스라고 합니다. ADO.NET 우산 아래의 일부 클래스는 특정 데이터 공급자에 연결됩니다. 데이터 공급자는 ADO.NET 클래스와 기본 데이터 저장소 간에 정보를 전달할 수 있는 통신 채널로 생각할 수 있습니다. OleDb 및 ODBC와 같은 일반화된 공급자뿐만 아니라 특정 데이터베이스 시스템을 위해 특별히 설계된 공급자도 있습니다. 예를 들어 OleDb 공급자를 사용하여 Microsoft SQL Server 데이터베이스에 연결할 수 있지만 SqlClient 공급자는 SQL Server용으로 특별히 설계되고 최적화되었기 때문에 훨씬 더 효율적입니다.
프로그래밍 방식으로 데이터에 액세스할 때 일반적으로 사용되는 패턴은 다음과 같습니다.
- 데이터베이스에 대한 연결을 설정합니다.
- 명령을 실행합니다.
- 쿼리의 경우
SELECT
결과 레코드를 사용합니다.
이러한 각 단계를 수행하기 위한 별도의 ADO.NET 클래스가 있습니다. 예를 들어 SqlClient 공급자를 사용하여 데이터베이스에 연결하려면 클래스를 SqlConnection
사용합니다. 데이터베이스에 INSERT
, UPDATE
또는 DELETE
SELECT
명령을 실행하려면 클래스를 SqlCommand
사용합니다.
트랜잭션 자습서 내의 데이터베이스 수정 래핑을 제외하고 TableAdapters 자동 생성 코드에는 데이터베이스에 연결하고, 명령을 실행하고, 데이터를 검색하고, 해당 데이터를 DataTable에 채우는 데 필요한 기능이 포함되어 있으므로 하위 수준 ADO.NET 코드를 직접 작성할 필요가 없습니다. 그러나 이러한 하위 수준 설정을 사용자 지정해야 하는 경우가 있을 수 있습니다. 다음 몇 단계를 통해 TableAdapters에서 내부적으로 사용하는 ADO.NET 개체를 탭하는 방법을 살펴보겠습니다.
1단계: 연결 속성을 사용하여 검사
각 TableAdapter 클래스에는 Connection
데이터베이스 연결 정보를 지정하는 속성이 있습니다. 이 속성의 데이터 형식 및 ConnectionString
값은 TableAdapter 구성 마법사에서 선택한 항목에 따라 결정됩니다. Typed DataSet에 TableAdapter를 처음 추가할 때 이 마법사는 데이터베이스 원본을 요청합니다(그림 1 참조). 이 첫 번째 단계의 드롭다운 목록에는 구성 파일에 지정된 데이터베이스와 서버 탐색기의 데이터 연결에 있는 다른 데이터베이스가 포함됩니다. 사용하려는 데이터베이스가 드롭다운 목록에 없는 경우 새 연결 단추를 클릭하고 필요한 연결 정보를 제공하여 새 데이터베이스 연결을 지정할 수 있습니다.
그림 1: TableAdapter 구성 마법사의 첫 번째 단계(전체 크기 이미지를 보려면 클릭)
잠시 시간을 내어 TableAdapter 속성 Connection
에 대한 코드를 검사해 보겠습니다.
데이터 액세스 계층 만들기 자습서에서 설명한 것처럼 클래스 뷰 창으로 이동하여 적절한 클래스로 드릴다운한 다음 멤버 이름을 두 번 클릭하여 자동으로 생성된 TableAdapter 코드를 볼 수 있습니다.
보기 메뉴로 이동하여 클래스 보기를 선택하거나 Ctrl+Shift+C를 입력하여 클래스 뷰 창으로 이동합니다. 클래스 뷰 창의 상단에서 네임스페이스 NorthwindTableAdapters
로 드릴다운하고 클래스 ProductsTableAdapter
를 선택합니다.
ProductsTableAdapter
멤버가 그림 2와 같이 클래스 뷰의 아래쪽 절반에 표시됩니다. 속성을 두 번 클릭하여 Connection
해당 코드를 확인합니다.
그림 2: 클래스 뷰에서 연결 속성을 Double-Click 자동 생성된 코드를 봅니다.
TableAdapter의 Connection
속성 및 기타 연결 관련 코드는 다음과 같습니다.
private System.Data.SqlClient.SqlConnection _connection;
private void InitConnection() {
this._connection = new System.Data.SqlClient.SqlConnection();
this._connection.ConnectionString =
ConfigurationManager.ConnectionStrings["NORTHWNDConnectionString"].ConnectionString;
}
internal System.Data.SqlClient.SqlConnection Connection {
get {
if ((this._connection == null)) {
this.InitConnection();
}
return this._connection;
}
set {
this._connection = value;
if ((this.Adapter.InsertCommand != null)) {
this.Adapter.InsertCommand.Connection = value;
}
if ((this.Adapter.DeleteCommand != null)) {
this.Adapter.DeleteCommand.Connection = value;
}
if ((this.Adapter.UpdateCommand != null)) {
this.Adapter.UpdateCommand.Connection = value;
}
for (int i = 0; (i < this.CommandCollection.Length); i = (i + 1)) {
if ((this.CommandCollection[i] != null)) {
((System.Data.SqlClient.SqlCommand)
(this.CommandCollection[i])).Connection = value;
}
}
}
}
TableAdapter 클래스가 인스턴스화되면 멤버 변수 _connection
는 같아 null
집니다. 속성에 Connection
액세스하면 먼저 멤버 변수가 _connection
인스턴스화되었는지 확인합니다. 조건이 충족되지 않으면 InitConnection
메서드가 호출됩니다. 이 메서드는 _connection
을 인스턴스화하며, 해당 ConnectionString
속성을 TableAdapter 구성 마법사의 첫 번째 단계에서 지정된 연결 문자열 값으로 설정합니다.
Connection
속성은 SqlConnection
객체에도 할당될 수 있습니다. 이렇게 하면 새 SqlConnection
개체를 각 TableAdapter 개체 SqlCommand
와 연결합니다.
2단계: Connection-Level 설정 노출
연결 정보는 TableAdapter 내에서 캡슐화된 상태로 유지되어야 하며 애플리케이션 아키텍처의 다른 계층에서 액세스할 수 없습니다. 그러나 쿼리, 사용자 또는 ASP.NET 페이지에 대해 TableAdapter의 연결 수준 정보에 액세스하거나 사용자 지정할 수 있어야 하는 시나리오가 있을 수 있습니다.
ProductsTableAdapter
에서 DataSet을 확장하여 비즈니스 논리 계층이 TableAdapter에서 사용하는 연결 문자열을 읽거나 변경할 수 있도록 Northwind
에 ConnectionString
속성을 포함해 봅시다.
비고
연결 문자열은 사용할 공급자, 데이터베이스 위치, 인증 자격 증명 및 기타 데이터베이스 관련 설정과 같은 데이터베이스 연결 정보를 지정하는 문자열입니다. 다양한 데이터 저장소 및 공급자가 사용하는 연결 문자열 패턴 목록은 ConnectionStrings.com 참조하세요.
데이터 액세스 계층 만들기 자습서에서 설명한 것처럼 Typed DataSet의 자동 생성 클래스는 부분 클래스를 사용하여 확장할 수 있습니다. 먼저 프로젝트 ConnectionAndCommandSettings
의 ~/App_Code/DAL
폴더 아래에 새 하위 폴더를 만듭니다.
그림 3: 명명된 하위 폴더 추가 ConnectionAndCommandSettings
명명 ProductsTableAdapter.ConnectionAndCommandSettings.cs
된 새 클래스 파일을 추가하고 다음 코드를 입력합니다.
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
namespace NorthwindTableAdapters
{
public partial class ProductsTableAdapter
{
public string ConnectionString
{
get
{
return this.Connection.ConnectionString;
}
set
{
this.Connection.ConnectionString = value;
}
}
}
}
이 partial 클래스는 TableAdapter의 public
클래스에 ConnectionString
라는 속성을 추가하여, 모든 계층이 기본 연결에 대한 연결 문자열을 읽거나 업데이트할 수 있도록 합니다.
이 partial 클래스를 만들고 저장한 후, ProductsBLL
클래스를 엽니다. 기존 메서드 중 하나로 이동하여 입력 Adapter
한 다음 마침표 키를 눌러 IntelliSense를 표시합니다. IntelliSense에서 사용할 수 있는 새 ConnectionString
속성이 표시되어야 합니다. 즉, BLL에서 이 값을 프로그래밍 방식으로 읽거나 조정할 수 있습니다.
전체 연결 개체 노출
이 partial 클래스는 기본 연결 개체의 속성을 하나만 노출합니다 ConnectionString
. TableAdapter의 범위를 벗어나 전체 연결 개체를 사용할 수 있도록 하려면, Connection
속성의 보호 수준을 변경하는 방법도 있습니다. 1단계에서 검사한 자동 생성 코드는 TableAdapter의 Connection
속성이 동일한 어셈블리에 있는 클래스에만 액세스할 수 있음을 나타냅니다internal
. 그러나 TableAdapter 속성을 ConnectionModifier
통해 변경할 수 있습니다.
DataSet을 Northwind
열고, 디자이너에서 ProductsTableAdapter
을 클릭한 다음 속성 창으로 이동합니다. 기본값ConnectionModifier
으로 Assembly
설정된 것을 볼 수 있습니다. Typed DataSet 어셈블리 외부에서 Connection
속성을 사용할 수 있도록, ConnectionModifier
속성을 Public
로 변경하십시오.
그림 4: Connection
속성을 통해 ConnectionModifier
속성의 접근성 수준을 구성할 수 있습니다(전체 크기 이미지를 보려면 클릭).
DataSet을 저장한 다음 ProductsBLL
클래스으로 돌아가십시오. 이전과 마찬가지로 기존 메서드 중 하나로 이동하여 입력 Adapter
한 다음 마침표 키를 눌러 IntelliSense를 표시합니다. 목록에는 속성이 Connection
포함되어야 합니다. 즉, 이제 BLL에서 모든 연결 수준 설정을 프로그래밍 방식으로 읽거나 할당할 수 있습니다.
3단계: Command-Related 속성 검사
TableAdapter는 기본적으로 자동 생성된 INSERT
, UPDATE
, DELETE
문이 있는 주 쿼리로 구성됩니다. 이 기본 쿼리 INSERT
UPDATE
및 DELETE
문은 TableAdapter 코드에서 속성을 통해 Adapter
ADO.NET 데이터 어댑터 개체로 구현됩니다. 속성 Connection
Adapter
과 마찬가지로 속성의 데이터 형식은 사용되는 데이터 공급자에 의해 결정됩니다. 이러한 자습서에서는 SqlClient 공급자를 사용하므로 Adapter
속성은 형식 SqlDataAdapter
입니다.
TableAdapter의Adapter
속성에는SqlCommand
, INSERT
, UPDATE
문을 실행하는 데 사용하는 DELETE
유형의 세 가지 속성이 있습니다.
InsertCommand
UpdateCommand
DeleteCommand
SqlCommand
개체는 데이터베이스에 특정 쿼리를 전송하는 역할을 하며 실행할 임시 SQL 문 또는 저장 프로시저를 포함하는 속성CommandText
과 Parameters
개체 컬렉션 SqlParameter
인 속성이 있습니다.
데이터 액세스 계층 만들기 자습서에서 보았듯이 이러한 명령 개체는 속성 창을 통해 사용자 지정할 수 있습니다.
TableAdapter는 주 쿼리 외에도 호출될 때 지정된 명령을 데이터베이스에 디스패치하는 다양한 메서드를 포함할 수 있습니다. 모든 추가 메서드에 대한 기본 쿼리 명령 개체와 명령 개체는 TableAdapter의 CommandCollection
속성에 저장됩니다.
DataSet의 ProductsTableAdapter
에서 Northwind
에 의해 생성된 코드와 두 속성과 그 지원 멤버 변수 및 도우미 메서드를 잠시 살펴보겠습니다.
private System.Data.SqlClient.SqlDataAdapter _adapter;
private void InitAdapter() {
this._adapter = new System.Data.SqlClient.SqlDataAdapter();
... Code that creates the InsertCommand, UpdateCommand, ...
... and DeleteCommand instances - omitted for brevity ...
}
private System.Data.SqlClient.SqlDataAdapter Adapter {
get {
if ((this._adapter == null)) {
this.InitAdapter();
}
return this._adapter;
}
}
private System.Data.SqlClient.SqlCommand[] _commandCollection;
private void InitCommandCollection() {
this._commandCollection = new System.Data.SqlClient.SqlCommand[9];
... Code that creates the command objects for the main query and the ...
... ProductsTableAdapter�s other eight methods - omitted for brevity ...
}
protected System.Data.SqlClient.SqlCommand[] CommandCollection {
get {
if ((this._commandCollection == null)) {
this.InitCommandCollection();
}
return this._commandCollection;
}
}
Adapter
및 CommandCollection
속성에 대한 코드는 Connection
속성의 코드를 밀접하게 모방합니다. 속성에 사용되는 개체를 포함하는 멤버 변수가 있습니다. 속성 get
접근자는 해당 멤버 변수가 null
상태인지 확인하는 것으로 시작합니다. 이 경우 멤버 변수의 인스턴스를 만들고 핵심 명령 관련 속성을 할당하는 초기화 메서드가 호출됩니다.
4단계: Command-Level 설정 노출
이상적으로 명령 수준 정보는 데이터 액세스 계층 내에 캡슐화되어 있어야 합니다. 그러나 이 정보가 아키텍처의 다른 계층에서 필요한 경우 연결 수준 설정과 마찬가지로 부분 클래스를 통해 노출될 수 있습니다.
TableAdapter에는 단일 Connection
속성만 있으므로 연결 수준 설정을 노출하는 코드는 매우 간단합니다. TableAdapter에는 속성에 여러 명령 개체(, 및 가변 수의 명령 개체InsertCommand
UpdateCommand
DeleteCommand
)가 있을 수 있으므로 명령 CommandCollection
수준 설정을 수정할 때는 상황이 좀 더 복잡합니다. 명령 수준 설정을 업데이트할 때 이러한 설정은 모든 명령 개체로 전파되어야 합니다.
예를 들어 TableAdapter에서 실행하는 데 특별한 시간이 걸린 특정 쿼리가 있다고 상상해 보십시오. TableAdapter를 사용하여 이러한 쿼리 중 하나를 실행하는 경우 명령 개체의 CommandTimeout
속성을 늘릴 수 있습니다. 이 속성은 명령이 실행되기를 기다리는 시간(초)을 지정하고 기본값은 30입니다.
BLL에서 CommandTimeout
속성을 조정할 수 있도록 하려면 2단계(public
)에서 생성된 partial 클래스 파일 내에 다음 ProductsDataTable
메서드를 ProductsTableAdapter.ConnectionAndCommandSettings.cs
에 추가하십시오.
public void SetCommandTimeout(int timeout)
{
if (this.Adapter.InsertCommand != null)
this.Adapter.InsertCommand.CommandTimeout = timeout;
if (this.Adapter.DeleteCommand != null)
this.Adapter.DeleteCommand.CommandTimeout = timeout;
if (this.Adapter.UpdateCommand != null)
this.Adapter.UpdateCommand.CommandTimeout = timeout;
for (int i = 0; i < this.CommandCollection.Length; i++)
if (this.CommandCollection[i] != null)
this.CommandCollection[i].CommandTimeout = timeout;
}
BLL 또는 프레젠테이션 계층에서 이 메서드를 호출하여 해당 TableAdapter 인스턴스의 모든 명령 문제에 대한 명령 시간 제한을 설정할 수 있습니다.
비고
Adapter
및 CommandCollection
속성은 private
로 표시되어, TableAdapter 내의 코드에서만 액세스할 수 있음을 의미합니다. 속성과 Connection
달리 이러한 액세스 한정자는 구성할 수 없습니다. 따라서 아키텍처의 다른 계층에 명령 수준 속성을 노출해야 하는 경우, public
메서드 또는 속성을 제공해야 하며, 이는 위에서 설명한 부분 클래스 접근 방식을 사용하여 private
명령 개체를 읽거나 쓰는 역할을 합니다.
요약
Typed DataSet 내의 TableAdapters는 데이터 액세스 세부 정보 및 복잡성을 캡슐화하는 역할을 합니다. TableAdapters를 사용하면 데이터베이스에 연결하거나 명령을 실행하거나 결과를 DataTable로 채우기 위해 ADO.NET 코드를 작성하는 것에 대해 걱정할 필요가 없습니다. 그것은 모두 우리를 위해 자동으로 처리됩니다.
그러나 연결 문자열 또는 기본 연결 또는 명령 시간 제한 값 변경과 같은 하위 수준 ADO.NET 세부 정보를 사용자 지정해야 하는 경우가 있을 수 있습니다. TableAdapter에는 자동으로 생성된 Connection
, Adapter
, 및 CommandCollection
속성이 있지만, 기본적으로 이러한 속성은 internal
이거나 private
입니다. 이 내부 정보는 부분 클래스를 사용하여 TableAdapter를 확장하여 메서드 또는 속성을 포함 public
함으로써 노출될 수 있습니다. 대안으로, TableAdapter의 Connection
속성 액세스 한정자를 ConnectionModifier
속성을 통해 구성할 수 있습니다.
행복한 프로그래밍!
작성자 정보
7개의 ASP/ASP.NET 책의 저자이자 4GuysFromRolla.com 창립자인 Scott Mitchell은 1998년부터 Microsoft 웹 기술을 연구해 왔습니다. Scott은 독립 컨설턴트, 트레이너 및 작가로 일합니다. 그의 최신 책은 Sams Teach Yourself ASP.NET 2.0 in 24 Hours입니다. 그에게 mitchell@4GuysFromRolla.com으로 연락할 수 있습니다.
특별히 감사드립니다.
이 자습서 시리즈는 많은 유용한 검토자가 검토했습니다. 이 자습서의 수석 검토자는 버나데트 리, S 렌 제이콥 로리센, 테레사 머피, 힐튼 가이세나우였습니다. 예정된 MSDN 문서를 검토하는 데 관심이 있으신가요? 그렇다면 mitchell@4GuysFromRolla.com으로 메시지를 보내 주세요.