데이터 집합 소개

데이터 집합은 연결되지 않은 캐시에 데이터를 저장합니다. 데이터 집합의 구조는 관계형 데이터베이스 구조와 유사하며 테이블, 행 및 열로 구성된 계층적 개체 모델을 취합니다. 또한, 데이터 집합의 구조에는 데이터 집합에 대해 정의된 제약 조건 및 관계도 포함됩니다.

참고   데이터 소스에 연결되지 않은 상태에서 테이블 및 행 집합에 대해 작업하려면 데이터 집합을 사용합니다. 데이터 액세스를 디자인할 때 데이터 집합을 사용하는 것이 항상 최선의 해결책이라고는 할 수 없습니다. 자세한 내용은 데이터 액세스 전략 권장 사항을 참조하십시오.

.NET Framework 네임스페이스의 다음 부분을 사용하여 데이터 집합을 만들고 조작할 수 있습니다.

데이터 집합 네임스페이스

사용자는 속성 및 컬렉션같은 프로그래밍의 표준 구성 요소를 통해 데이터 집합의 기본 요소를 볼 수 있습니다. 예를 들면, 다음과 같습니다.

  • DataSet 클래스에는 데이터 테이블로 이루어진 Tables 컬렉션과 DataRelation 개체로 이루어진 Relations 컬렉션이 들어 있습니다.
  • DataTable 클래스에는 테이블 행을 모아 놓은 Rows 컬렉션, 데이터 열을 모아 놓은 Columns 컬렉션 그리고 각 데이터간 관계를 모아 놓은 ChildRelationsParentRelations 컬렉션이 포함되어 있습니다.
  • DataRow 클래스의 RowState 속성은 데이터 테이블이 데이터베이스로부터 로드된 후 행이 변경되었는지 그리고 어떻게 변경되었는지를 나타냅니다. RowState 속성에 사용할 수 있는 값으로는 Deleted, Modified, NewUnchanged가 있습니다.

데이터 집합, 스키마 및 XML

ADO.NET 데이터 집합은 XML로 나타낼 수 있는 데이터 뷰, 즉 관계형 뷰입니다. Visual Studio 및 .NET Framework 에서는 XML 형식을 사용하여 모든 종류의 데이터를 저장하고 전송합니다. 데이터 집합은 본질적으로 XML과 잘 어울리므로 데이터 집합과 XML 사이의 이러한 관계를 통해 데이터 집합의 다음 기능을 사용할 수 있습니다.

  • 데이터 집합의 구조(예: 테이블, 열, 관계 및 제약 조건)는 XML 스키마에서 정의합니다. XML 스키마는 W3C(World Wide Web 컨소시엄) 표준 기반 형식을 말하며 XML 데이터의 구조를 정의하는 데 사용됩니다. 데이터 집합에서는 ReadXmlSchemaWriteXmlSchema 메서드를 사용하여 구조적 정보를 저장하는 스키마를 읽고 쓸 수 있습니다. 사용할 스키마가 없는 경우 데이터 집합에서는 InferXmlSchema 메서드를 통해 관계형으로 구조화된 XML 문서의 데이터에서 스키마를 추론할 수 있습니다. 데이터 집합과 스키마에 대한 자세한 내용은 XML 스키마 소개를 참조하십시오.
  • 스키마 정보를 사용하여 테이블 및 열과 같은 데이터 구조를 클래스 멤버로 정의하는 데이터 집합 클래스를 생성할 수 있습니다. 자세한 내용은 아래의 "형식화된 데이터 집합과 형식화되지 않은 데이터 집합" 부분을 참조하십시오.
  • 데이터 집합의 ReadXml 메서드를 사용하면 XML 문서나 스트림을 데이터 집합으로 읽어 올 수 있으며 WriteXml 메서드를 사용하면 데이터 집합을 XML로 쓸 수 있습니다. XML은 서로 다른 응용 프로그램 간의 데이터 표준 교환 형식이므로 다른 응용 프로그램에서 XML 형식의 정보가 들어 있는 데이터 집합을 전송해 와도 해당 데이터 집합을 로드할 수 있습니다. 이와 마찬가지로 데이터 집합은 데이터를 XML 스트림 또는 문서로 쓸 수 있으며 이를 다른 응용 프로그램과 공유할 수도 있고 표준 형식으로 저장만 해 둘 수도 있습니다.
  • 데이터 집합의 내용에 대한 XML 뷰(XMLDataDocument 개체)를 만든 후 데이터 집합을 사용하는 관계형 메서드 또는 XML 메서드를 사용하여 데이터를 보고 조작할 수 있습니다. 두 개의 뷰는 변경될 때마다 자동으로 동기화됩니다.

형식화된 데이터 집합과 형식화되지 않은 데이터 집합

데이터 집합에는 형식화된 데이터 집합 및 형식화되지 않은 데이터 집합의 두 가지 종류가 있습니다. 형식화된 데이터 집합은 기본 DataSet 클래스에서 파생되며 XML 스키마 파일(.xsd 파일)의 정보를 사용하여 새로운 클래스를 생성합니다. 테이블, 열 등의 스키마 정보가 생성되면 첫 번째 클래스 개체 및 속성 집합으로서 이 새로운 데이터 집합 클래스에 컴파일됩니다.

참고   데이터 집합 스키마에 대한 자세한 내용은 XML 스키마 및 데이터를 참조하십시오.

형식화된 DataSet 클래스는 기본 DataSet 클래스에서 상속되기 때문에 DataSet 클래스의 모든 기능을 그대로 가져오며 DataSet 클래스의 인스턴스를 매개 변수로 받는 메서드와 함께 사용할 수 있습니다.

이와 달리 형식화되지 않은 데이터 집합에는 내장 스키마가 없습니다. 형식화된 데이터 집합에서와 같이 형식화되지 않은 데이터 집합에도 테이블, 열 등이 들어 있지만 이들은 컬렉션으로만 표시됩니다. 그러나 형식화되지 않은 데이터 집합에서 테이블 및 기타 데이터 구성 요소를 직접 만든 후에는 데이터 집합의 WriteXmlSchema 메서드를 사용하여 데이터 집합의 구조를 스키마로 내보낼 수 있습니다.

응용 프로그램에서는 어떤 형식의 데이터 집합을 사용해도 되지만 Visual Studio에는 형식화된 데이터 집합을 지원하는 도구가 더 많으며 이러한 도구를 사용하면 형식화된 데이터 집합을 사용한 프로그래밍 작업을 더욱 쉽게 수행할 수 있고 오류도 줄어듭니다.

형식화된 데이터 집합 및 형식화되지 않은 데이터 집합에서의 데이터 액세스 비교

형식화된 데이터 집합의 클래스에는 형식화된 데이터 집합의 테이블과 열이 첫 번째 개체가 되는 개체 모델이 있습니다. 예를 들어, 형식화된 데이터 집합으로 작업하는 경우 다음과 같은 코드를 사용하여 열을 참조할 수 있습니다.

' Visual Basic
' This accesses the CustomerID column in the first row of 
' the Customers table.
Dim s As String
s = dsCustomersOrders1.Customers(0).CustomerID

// C#
// This accesses the CustomerID column in the first row of 
// the Customers table.
string s;
s = dsCustomersOrders1.Customers[0].CustomerID;

이와는 반대로 형식화되지 않은 데이터 집합으로 작업하는 경우 다음과 같은 코드를 사용합니다.

' Visual Basic
Dim s As String
s = CType(dsCustomersOrders1.Tables("Customers").Rows(0).Item("CustomerID"), String)

// C#
string s = (string) dsCustomersOrders1.Tables["Customers"].Rows[0]["CustomerID"];

형식화된 액세스는 읽기가 더 쉬울 뿐만 아니라 Visual Studio 코드 편집기에서 IntelliSense가 완벽하게 지원됩니다. 작업하기 쉽다는 이점 이외에 형식화된 데이터 집합에 대한 구문에서는 컴파일 타임에 형식을 검사하므로 데이터 집합 멤버에 값을 할당할 때 오류가 발생할 가능성이 크게 줄어듭니다. 또한, 액세스가 런타임에 컬렉션을 통해 결정되지 않고 컴파일 타임에 결정되므로 형식화된 데이터 집합의 테이블과 열에 대한 액세스는 런타임에 약간 더 빠릅니다.

형식화된 데이터 집합에 장점이 많지만 형식화되지 않은 데이터 집합을 사용하는 것이 유용한 경우도 많이 있습니다. 데이터 집합에 스키마가 없는 경우가 이에 해당됩니다. 예를 들어, 응용 프로그램이 데이터 집합을 반환하는 구성 요소와 상호 작용할 때 반환되는 데이터 집합의 구조를 미리 알지 못하는 경우 이런 상황이 발생할 수 있습니다. 이와 마찬가지로, 정적이지 않거나 예측할 수 없는 구조의 데이터로 작업하는 경우 데이터 집합을 사용하면 데이터 구조가 변경될 때마다 형식화된 데이터 집합 클래스를 다시 생성해야하므로 비현실적입니다.

보다 일반적으로, 사용 가능한 스키마가 없는 상태에서 데이터 집합을 동적으로 만들어야 하는 경우가 많이 있습니다. 이 경우, 데이터가 관계형으로 표현되는 한 데이터 집합은 정보를 편리하게 보관할 수 있는 구조입니다. 이와 동시에 정보를 serialize하여 다른 프로세스로 전달해 주거나 XML 파일을 기록하는 등 데이터 집합의 기능을 사용할 수 있습니다.

데이터 집합의 대/소문자 구분

데이터 집합 내에서 테이블 및 열 이름은 기본적으로 대/소문자를 구분하지 않습니다. 즉, "Customers"라는 데이터 집합의 테이블은 "customers"로도 참조될 수 있습니다. 이러한 사항은 대/소문자만으로는 데이터 요소의 이름을 구별할 수 없는 SQL Server를 비롯한 여러 데이터베이스에서 사용되는 명명 규칙과 같습니다.

참고   데이터 집합과 달리 XML 문서는 대/소문자를 구분합니다. 따라서, 스키마에 정의된 데이터 요소의 이름은 대/소문자를 구분합니다. 예를 들어, 스키마는 스키마 프로토콜을 통해 "Customers"라는 테이블과 "customers"라는 테이블을 서로 다른 테이블로 정의하고 포함할 수 있습니다. 그러므로 스키마를 사용하여 데이터 집합 클래스를 생성하는 경우 이름 충돌이 발생할 수 있습니다. 자세한 내용은 XML 요소, 특성 및 형식을 참조하십시오.

그러나 대/소문자 구분은 데이터 집합 내에서 데이터가 해석되는 방식을 결정하는 한 요인이 될 수 있습니다. 예를 들어, 데이터 집합 테이블에 포함된 데이터를 필터링하는 경우 대/소문자 구분 여부에 따라 검색 조건이 다른 결과를 반환할 수 있습니다. 데이터 집합의 CaseSensitive 속성을 설정하면 필터링, 검색 및 정렬 시 대/소문자를 구분할지 여부를 결정할 수 있습니다. 데이터 집합의 모든 테이블은 기본적으로 이 속성 값을 상속합니다. 개별 테이블에 대해 이 속성을 재정의할 수 있습니다.

데이터 집합 채우기

데이터 집합은 일종의 컨테이너이므로 데이터로 채워야 합니다. 데이터 집합을 채울 때 다양한 이벤트가 발생하고 제약 조건 검사가 적용되는 등 여러 작업이 이루어집니다. 데이터 집합을 업데이트하는 방법과 업데이트와 관련된 문제에 대한 자세한 내용은 Visual Studio .NET에서 데이터 집합 업데이트를 참조하십시오.

다음과 같은 다양한 방법으로 데이터 집합을 채울 수 있습니다.

  • 데이터 어댑터의 Fill 메서드를 호출합니다. 그러면 어댑터가 SQL 문 또는 저장 프로시저를 실행하고 그 결과가 데이터 집합의 테이블에 채워집니다. 데이터 집합에 테이블이 여러 개 있는 경우 각각의 테이블마다 데이터 어댑터가 있게 되므로 각 어댑터의 Fill 메서드를 개별적으로 호출해야 합니다.

    데이터 집합을 채우는 방법에 대한 자세한 내용은 데이터 어댑터 소개데이터 어댑터 만들기를 참조하십시오. 데이터 어댑터를 사용하여 데이터 집합을 채우는 방법에 대한 자세한 내용은 DataAdapter에서 DataSet 채우기를 참조하십시오.

  • DataRow 개체를 만들고 이 개체들을 테이블의 Rows 컬렉션에 추가하여 데이터 집합의 테이블을 직접 채웁니다. 이 작업은 런타임에만 가능하며 디자인 타임에는 Rows 컬렉션을 설정할 수 없습니다. 자세한 내용은 테이블에 데이터 추가를 참조하십시오.

  • XML 문서나 스트림을 데이터 집합으로 읽을 수도 있습니다. 자세한 내용은 ReadXml 메서드를 참조하십시오.

  • 다른 데이터 집합의 내용을 병합(복사)합니다. 응용 프로그램이 다양한 XML Web services 같은 여러 개의 소스에서 데이터 집합을 가져와서 단일 데이터 집합으로 통합하는 경우 이 방법이 유용합니다. 자세한 내용은 DataSet.Merge 메서드를 참조하십시오.

데이터 집합에서 레코드의 위치 및 탐색

데이터 집합은 연결이 완전히 끊어져 있는 데이터 컨테이너이므로 ADO 레코드 집합과는 달리 데이터 집합에서는 현재 레코드라는 개념이 필요하지 않으며 그 개념을 지원하지도 않습니다. 하지만 데이터 집합의 모든 레코드를 사용할 수는 있습니다.

현재 레코드가 없으므로 현재 레코드를 가리키는 특정 속성이 없으며 한 레코드에서 다른 레코드로 이동하기 위한 메서드나 속성도 없습니다. 이와 달리 ADO 레코드 집합에서는 한 레코드에서 다른 레코드로 이동하기 위해 사용되는 레코드의 절대 위치 및 메서드를 지원합니다. 데이터 집합에 있는 각각의 테이블에는 개체로 액세스할 수 있으며 각 테이블에는 행 컬렉션이 포함되어 있습니다. 컬렉션의 인덱스를 통해 행에 액세스하거나 사용하는 프로그래밍 언어에서 컬렉션 관련 문을 사용하여 행에 액세스하는 것처럼, 각 테이블에 대해서는 컬렉션에 대해 작업하듯이 할 수 있습니다.

참고   Windows Forms의 컨트롤을 데이터 집합으로 바인딩하는 경우 폼의 바인딩 아키텍처를 사용하면 개별 레코드에 대한 액세스를 단순화할 수 있습니다. 자세한 내용은 Windows Forms에서 데이터 탐색을 참조하십시오.

관련 테이블 및 DataRelation 개체

데이터 집합에 테이블이 여러 개 있는 경우 테이블 내의 정보를 서로 관련시킬 수 있습니다. 데이터 집합에서는 기본적으로 이런 관계를 인식하지 못하므로 관련 테이블의 데이터로 작업하려면 데이터 집합에 속한 테이블 간의 관계를 설명하는 DataRelation 개체를 만들어야 합니다. DataRelation 개체를 사용하여 프로그래밍 방식으로 부모 레코드에 대해 자식 레코드를 페치(fetch)하고 반대로 자식 레코드에 대해 부모 레코드를 페치(fetch)할 수도 있습니다.

예를 들어, Northwind 데이터베이스같은 고객 및 주문 데이터가 있다고 할 때 Customers 테이블에는 다음과 같은 레코드가 포함될 수 있습니다.

CustomerID   CompanyName               City
ALFKI        Alfreds Futterkiste       Berlin
ANTON        Antonio Moreno Taquerias  Mexico D.F.
AROUT        Around the Horn           London

데이터 집합에는 또한 주문 정보가 들어 있는 다른 테이블이 포함될 수 있습니다. Orders 테이블에는 고객 ID가 외래 키 열로 들어 있습니다. Orders 테이블의 일부 열은 다음과 같습니다.

OrderId    CustomerID    OrderDate
10692      ALFKI         10/03/1997
10702      ALFKI         10/13/1997
10365      ANTON         11/27/1996
10507      ANTON         4/15/1997

고객 한 명이 주문을 여러 번 할 수 있으므로 고객과 주문은 일대다 관계입니다. 예를 들어, 위의 테이블에서 고객 ALFKI는 주문을 두 번 했습니다.

DataRelation 개체를 사용하여 자식 또는 부모 테이블에서 관련 레코드를 가져올 수 있습니다. 예를 들어, 고객 ANTON에 관한 레코드로 작업하는 경우 이 고객의 주문에 대한 레코드 컬렉션을 불러올 수 있습니다. 마찬가지로 주문 번호 10507에 관한 레코드로 작업하는 경우 이 주문을 낸 고객(ANTON)에 대한 레코드를 DataRelation 개체를 사용하여 가져올 수 있습니다.

제약 조건

대부분의 데이터베이스와 같이 데이터 집합에서는 데이터의 무결성을 보장하기 위한 방법의 하나로 제약 조건을 지원합니다. 제약 조건은 테이블에서 행을 추가, 업데이트 또는 삭제할 때 적용되는 규칙입니다. 다음과 같이 두 종류의 제약 조건을 정의할 수 있습니다.

  • UNIQUE 제약 조건. 이 제약 조건은 열의 새 값이 테이블에서 고유한지 검사합니다.
  • 외래 키 제약 조건. 이 제약 조건은 마스터 테이블의 레코드가 업데이트되거나 삭제되는 경우 관련된 자식 레코드가 업데이트되는 방법에 관한 규칙을 정의합니다.

데이터 집합에서 제약 조건은 개별 테이블(외래 키 제약 조건) 또는 열(해당 열의 값이 고유하다는 것을 보장하는 UNIQUE 제약 조건)과 관련됩니다. 제약 조건은 UniqueConstraint 또는 ForeignKeyConstraint 형식의 개체로 구현된 후 테이블의 Constraints 컬렉션에 추가됩니다. UNIQUE 제약 조건의 경우에는 데이터 열의 Unique 속성만 true로 설정해도 지정할 수 있습니다.

데이터 집합에서는 제약 조건의 적용 여부를 지정하는 부울 EnforceConstraints 속성을 지원합니다. 기본적으로 이 속성은 true로 설정되어 있습니다. 그러나 제약 조건을 일시적으로 해제하는 것이 유용한 경우가 있습니다. 레코드를 변경함으로 인해 일시적으로 잘못된 상태가 유발될 때가 바로 그러한 경우입니다. 변경 작업을 완료하여 유효한 상태로 돌아간 후에는 제약 조건을 다시 활성화할 수 있습니다.

Visual Studio에서는 데이터 집합을 정의할 때 암시적으로 제약 조건을 만듭니다. 기본 키를 데이터 집합에 추가하면 기본 키 열에 대한 UNIQUE 제약 조건이 암시적으로 만들어집니다. Unique 속성을 true로 설정하면 다른 열에 대해서도 UNIQUE 제약 조건을 지정할 수 있습니다.

데이터 집합에서 DataRelation 개체를 만들면 외래 키 제약 조건이 만들어집니다. DataRelation 개체를 사용하면 관련 레코드에 대한 정보를 프로그래밍 방식으로 가져올 수 있을 뿐만 아니라 외래 키 제약 조건 규칙도 정의할 수 있습니다.

DataRelation 개체를 외래 키 제약 조건으로 사용하는 방법에 대한 자세한 내용은 DataRelation 개체 소개를 참조하십시오. 프로그래밍 방식으로 제약 조건을 만드는 방법에 대한 자세한 내용은 테이블에 제약 조건 추가를 참조하십시오.

데이터 집합 및 데이터 저장소 업데이트

데이터 집합에서 레코드가 변경되면 해당 변경 내용을 데이터베이스에 다시 써야 합니다. 데이터 집합과 해당 데이터 소스 사이에서 통신하는 데이터 어댑터의 Update 메서드를 호출하면 데이터 집합에서 데이터베이스로 변경 내용을 쓸 수 있습니다.

개별 레코드 조작에 사용되는 DataRow 클래스에는 RowState 속성이 있습니다. 이 속성의 값은 데이터 테이블이 데이터베이스에서 처음 로드된 이후 행의 변경 여부와 변경 방식을 나타냅니다. 가능한 값으로는 Deleted, Modified, NewUnchanged가 있습니다. Update 메서드는 RowState 속성의 값을 검사하여 데이터베이스에 써야 하는 레코드와 호출해야 할 특정 데이터베이스 명령(추가, 편집, 삭제)을 결정합니다.

데이터 업데이트에 대한 자세한 내용은 Visual Studio .NET에서 데이터 집합 업데이트를 참조하십시오.

참고 항목

ADO.NET을 사용한 데이터 액세스 소개 | 데이터 어댑터 소개 | 데이터 집합을 만들기 위한 Visual Studio 도구 | 구성 요소 디자이너를 사용하여 형식화된 데이터 집합 만들기 | XML 스키마 및 데이터 집합 만들기 | 기존의 형식화된 데이터 집합을 폼 또는 구성 요소에 추가 | 형식화되지 않은 데이터 집합을 폼 또는 구성 요소에 추가 | 데이터 연습