다음을 통해 공유


DataTable 열 추가하기 (C#)

저자 스콧 미첼

PDF 다운로드

TableAdapter 마법사를 사용하여 형식화된 데이터 세트를 만드는 경우 해당 DataTable에는 주 데이터베이스 쿼리에서 반환된 열이 포함됩니다. 그러나 DataTable에 추가 열을 포함해야 하는 경우가 있습니다. 이 자습서에서는 추가 DataTable 열이 필요할 때 저장 프로시저가 권장되는 이유를 알아봅니다.

소개

Typed DataSet에 TableAdapter를 추가할 때 해당 DataTable 스키마는 TableAdapter의 기본 쿼리에 의해 결정됩니다. 예를 들어 주 쿼리가 데이터 필드 A, BC를 반환하는 경우 DataTable에는 A, BC라는 세 개의 해당 열이 있습니다. TableAdapter는 주 쿼리 외에도 일부 매개 변수를 기반으로 데이터의 하위 집합을 반환하는 추가 쿼리를 포함할 수 있습니다. 예를 들어 모든 제품에 대한 정보를 반환하는 기본 쿼리 외에도 ProductsTableAdapter 제공된 매개 변수를 기반으로 특정 제품 정보를 반환하는 등의 GetProductsByCategoryID(categoryID)GetProductByProductID(productID)메서드도 포함됩니다.

TableAdapter의 주 쿼리와 연동되는 DataTable의 스키마 모델은 모든 TableAdapter 메서드가 주 쿼리에서 지정된 것과 동일하거나 적은 수의 데이터 필드를 반환할 때 효과적입니다. TableAdapter 메서드가 추가 데이터 필드를 반환해야 하는 경우 그에 따라 DataTable 스키마를 확장해야 합니다. 자습서에서는 마스터 레코드의 글머리 기호 목록을 사용하는 마스터/세부 정보 자습서에서 메서드를 추가하여 기본 쿼리에 정의된 데이터 필드 , , 와 각 범주에 연결된 제품 수를 보고하는 추가 데이터 필드 를 반환했습니다. 데이터 필드 값 CategoriesDataTable을 캡처하기 위해 이 새 메서드에 따라 열을 NumberOfProducts에 수동으로 추가했습니다.

파일 업로드 자습서에서 설명한 대로 임시 SQL 문을 사용하고 데이터 필드가 주 쿼리와 정확하게 일치하지 않는 메서드가 있는 TableAdapters를 사용하여 주의해야 합니다. TableAdapter 구성 마법사를 다시 실행하는 경우 해당 데이터 필드 목록이 기본 쿼리와 일치하게 모든 TableAdapter 메서드를 업데이트합니다. 따라서 사용자 지정된 열 목록을 가진 모든 메서드는 기본 쿼리의 열 목록으로 되돌리고 예상된 데이터를 반환하지 않습니다. 저장 프로시저를 사용할 때는 이 문제가 발생하지 않습니다.

이 자습서에서는 추가 열을 포함하도록 DataTable 스키마를 확장하는 방법을 살펴봅니다. 임시 SQL 문을 사용하는 경우 TableAdapter의 취약성으로 인해 이 자습서에서는 저장 프로시저를 사용합니다. 자세한 내용은 Typed DataSet의 TableAdapters에 대한 새 저장 프로시저 생성 자습서를 참조하여 TableAdapter에서 저장 프로시저를 사용하도록 구성하는 방법을 확인하세요.

1단계: 열 추가PriceQuartileProductsDataTable

Typed DataSet의 TableAdapters에 대한 새 저장 프로시저 만들기 자습서에서는 Typed DataSet이라는 형식NorthwindWithSprocs화된 데이터 세트를 만들었습니다. 이 DataSet에는 현재 두 개의 DataTable, ProductsDataTableEmployeesDataTable가 포함되어 있습니다. 다음과 ProductsTableAdapter 같은 세 가지 메서드가 있습니다.

  • GetProducts - 테이블의 모든 레코드 Products 를 반환하는 기본 쿼리
  • GetProductsByCategoryID(categoryID) - 지정된 categoryID를 가진 모든 제품을 반환합니다.
  • GetProductByProductID(productID) - 지정된 productID를 사용하여 특정 제품을 반환합니다.

기본 쿼리와 두 개의 추가 메서드는 모두 동일한 데이터 필드 집합, 즉 테이블의 모든 열을 반환합니다 Products . 상호 관련된 하위 쿼리나 JOIN 또는 Categories 또는 Suppliers 테이블에서 관련 데이터를 가져오는 과정이 없습니다. 따라서 ProductsDataTable의 각 필드는 Products 테이블에 해당하는 열을 가지고 있습니다.

이 자습서에서는 모든 제품을 반환하는 명명된 ProductsTableAdapterGetProductsWithPriceQuartile 메서드를 추가해 보겠습니다. 표준 제품 데이터 필드 GetProductsWithPriceQuartile 외에도 제품 가격이 어느 사분위수에 해당하는지를 나타내는 PriceQuartile 데이터 필드가 포함됩니다. 예를 들어, 가격이 상위 25%에 해당하는% 제품은 값이 1이 될 것이고, 가격이 하위 25%에 해당하는% 제품은 값이 4가 될 것입니다. 우리가 이 정보를 반환하기 위한 저장 프로시저를 만들기 전에, 먼저 ProductsDataTable에 메서드를 사용할 때의 PriceQuartile 결과를 저장할 GetProductsWithPriceQuartile 열을 포함하도록 업데이트해야 합니다.

DataSet을 NorthwindWithSprocs 열고 ProductsDataTable에서 마우스 오른쪽 버튼을 클릭합니다. 상황에 맞는 메뉴에서 추가를 선택한 다음 열을 선택합니다.

ProductsDataTable에 새 열 추가

그림 1: 새 열에 ProductsDataTable 추가(전체 크기 이미지를 보려면 클릭)

그러면 DataTable에 형식 System.String의 새로운 열인 Column1이 추가됩니다. 1에서 4 사이의 숫자를 보유하는 데 사용되므로 이 열의 이름을 PriceQuartile 및 해당 형식 System.Int32 으로 업데이트해야 합니다. 속성 창에서 ProductsDataTable에 새로 추가된 열을 선택하고, Name 속성을 PriceQuartile로 설정하고 DataTypeSystem.Int32 속성을 설정합니다.

새 열의 이름 및 DataType 속성 설정

그림 2: 새 열 NameDataType 속성 설정(전체 크기 이미지를 보려면 클릭)

그림 2와 같이 열의 값이 고유해야 하는지 여부, 열이 자동 증가 열인 경우, 데이터베이스 NULL 값 허용 여부 등과 같이 설정할 수 있는 추가 속성이 있습니다. 이러한 값을 기본값으로 설정합니다.

2단계: 메서드 만들기GetProductsWithPriceQuartile

이제 ProductsDataTablePriceQuartile 열을 포함하도록 업데이트되었으므로, 우리는 GetProductsWithPriceQuartile 메서드를 만들 준비가 완료되었습니다. 먼저 TableAdapter를 마우스 오른쪽 단추로 클릭하고 상황에 맞는 메뉴에서 쿼리 추가를 선택합니다. 그러면 TableAdapter 쿼리 구성 마법사가 표시됩니다. 이 마법사는 임시 SQL 문 또는 새 저장 프로시저 또는 기존 저장 프로시저를 사용할지 여부를 먼저 묻는 메시지를 표시합니다. 가격 사분위수 데이터를 반환하는 저장 프로시저가 아직 없으므로 TableAdapter에서 이 저장 프로시저를 만들 수 있도록 허용해 보겠습니다. 새 저장 프로시저 만들기 옵션을 선택하고 다음을 클릭합니다.

TableAdapter 마법사에 저장 프로시저를 만들도록 지시합니다.

그림 3: TableAdapter 마법사에 저장 프로시저를 만들도록 지시합니다(전체 크기 이미지를 보려면 클릭).

그림 4에 표시된 후속 화면에서 마법사는 추가할 쿼리 유형을 묻습니다. 메서드는 GetProductsWithPriceQuartile 테이블에서 모든 열과 레코드를 Products 반환하므로 행 옵션을 반환하는 SELECT 옵션을 선택하고 다음을 클릭합니다.

쿼리는 여러 행을 반환하는 SELECT 문이 됩니다.

그림 4: 쿼리는 여러 행을 SELECT 반환하는 문입니다(전체 크기 이미지를 보려면 클릭).

다음으로 쿼리 입력을 위한 SELECT 메시지가 표시됩니다. 마법사에 다음 쿼리를 입력합니다.

SELECT ProductID, ProductName, SupplierID, CategoryID, 
       QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, 
       ReorderLevel, Discontinued,
       NTILE(4) OVER (ORDER BY UnitPrice DESC) as PriceQuartile
FROM Products

위의 쿼리는 SQL Server 2005의 새 NTILE 함수 를 사용하여 결과를 내림차순으로 정렬된 값에 따라 UnitPrice 그룹이 결정되는 4개의 그룹으로 나눕니다.

아쉽게도 쿼리 작성기에서 키워드를 구문 분석 OVER 하는 방법을 모르고 위의 쿼리를 구문 분석할 때 오류가 표시됩니다. 따라서 쿼리 작성기를 사용하지 않고 마법사의 텍스트 상자에 위의 쿼리를 직접 입력합니다.

비고

NTILE 및 SQL Server 2005의 다른 순위 함수에 대한 자세한 내용은 ROW_NUMBER(Transact-SQL)SQL Server 2005 온라인 설명서순위 함수 섹션을 참조하세요.

쿼리를 SELECT 입력하고 다음을 클릭하면 마법사에서 만들 저장 프로시저의 이름을 제공하도록 요청합니다. 새 저장 프로시저 Products_SelectWithPriceQuartile 의 이름을 지정하고 다음을 클릭합니다.

저장 프로시저를 Products_SelectWithPriceQuartile 이름으로 지정하세요

그림 5: 저장 프로시저 Products_SelectWithPriceQuartile 이름 지정(전체 크기 이미지를 보려면 클릭)

마지막으로 TableAdapter 메서드의 이름을 지정하라는 메시지가 표시됩니다. DataTable 채우기 및 DataTable 반환 확인란을 모두 선택한 상태로 두고 메서드 FillWithPriceQuartile 이름을 지정합니다 GetProductsWithPriceQuartile.

TableAdapter의 메서드 이름을 지정하고 마침을 클릭합니다.

그림 6: TableAdapter 메서드의 이름을 지정하고 마침을 클릭합니다(전체 크기 이미지를 보려면 클릭).

쿼리가 SELECT 지정되고 저장 프로시저 및 TableAdapter 메서드가 명명된 상태에서 마침을 클릭하여 마법사를 완료합니다. 이 시점에서 마법사 OVER가 SQL 구문이나 문이 지원되지 않는다는 경고를 한두 번 보여줄 수 있습니다. 이러한 경고는 무시할 수 있습니다.

마법사를 완료한 후, TableAdapter에는 FillWithPriceQuartileGetProductsWithPriceQuartile 메서드가 포함되어야 하며 데이터베이스에는 Products_SelectWithPriceQuartile라는 저장 프로시저가 포함되어야 합니다. 잠시 시간을 내어 TableAdapter에 이 새 메서드가 실제로 포함되어 있고 저장 프로시저가 데이터베이스에 올바르게 추가되었는지 확인합니다. 데이터베이스를 확인할 때 저장 프로시저가 표시되지 않으면 저장 프로시저 폴더를 마우스 오른쪽 단추로 클릭하고 새로 고침을 선택합니다.

TableAdapter에 새 메서드가 추가되었는지 확인합니다.

그림 7: 새 메서드가 TableAdapter에 추가되었는지 확인

데이터베이스에 Products_SelectWithPriceQuartile 저장 프로시저가 포함되어 있는지 확인합니다.

그림 8: 데이터베이스에 저장 프로시저가 Products_SelectWithPriceQuartile 포함되어 있는지 확인합니다(전체 크기 이미지를 보려면 클릭).

비고

임시 SQL 문 대신 저장 프로시저를 사용할 경우의 이점 중 하나는 TableAdapter 구성 마법사를 다시 실행해도 저장 프로시저 열 목록이 수정되지 않는다는 점입니다. TableAdapter를 마우스 오른쪽 단추로 클릭하고 상황에 맞는 메뉴에서 구성 옵션을 선택하여 마법사를 시작한 다음 마침을 클릭하여 완료합니다. 다음으로 데이터베이스로 이동하여 저장 프로시저를 Products_SelectWithPriceQuartile 봅니다. 주목할 점은 열 목록이 수정되지 않았다는 것입니다. 임시 SQL 문을 사용했다면 TableAdapter 구성 마법사를 다시 실행하면 기본 쿼리 열 목록과 일치하도록 이 쿼리 열 목록을 되돌려 메서드에서 사용하는 GetProductsWithPriceQuartile 쿼리에서 NTILE 문을 제거했을 것입니다.

Data Access Layer의 GetProductsWithPriceQuartile 메서드가 호출되면, TableAdapter는 Products_SelectWithPriceQuartile 저장 프로시저를 실행하고 반환된 각 레코드에 대해 ProductsDataTable에 행을 추가합니다. 저장 프로시저에서 반환된 데이터 필드는 ProductsDataTable의 열에 매핑됩니다. 저장 프로시저에서 반환되는 PriceQuartile 데이터 필드가 있으므로, 해당 값은 ProductsDataTable 열에 PriceQuartile 할당됩니다.

쿼리가 데이터 필드를 PriceQuartile 반환 PriceQuartile 하지 않는 TableAdapter 메서드의 경우 열 값은 해당 DefaultValue 속성에 지정된 값입니다. 그림 2와 같이 이 값은 기본값으로 DBNull설정됩니다. 다른 기본값을 원하는 경우 속성을 적절하게 설정 DefaultValue 하기만 하면 됩니다. DefaultValue 값을 열 DataType 기준으로 유효한지 확인하십시오 (즉, System.Int32 열의 PriceQuartile 경우).

이 시점에서 DataTable에 열을 추가하는 데 필요한 단계를 수행했습니다. 이 추가 열이 예상대로 작동하는지 확인하려면 각 제품의 이름, 가격 및 가격 사분위수로 표시되는 ASP.NET 페이지를 만들어 보겠습니다. 하지만 이 작업을 수행하려면 먼저 DAL GetProductsWithPriceQuartile 메서드를 호출하는 메서드를 포함하도록 비즈니스 논리 계층을 업데이트해야 합니다. 다음으로 3단계에서 BLL을 업데이트한 다음 4단계에서 ASP.NET 페이지를 만듭니다.

3단계: 비즈니스 논리 계층 보강

프레젠테이션 계층에서 새 GetProductsWithPriceQuartile 메서드를 사용하기 전에 먼저 해당 메서드를 BLL에 추가해야 합니다. ProductsBLLWithSprocs 클래스 파일을 열고 다음 코드를 추가합니다.

[System.ComponentModel.DataObjectMethodAttribute
    (System.ComponentModel.DataObjectMethodType.Select, false)]
public NorthwindWithSprocs.ProductsDataTable GetProductsWithPriceQuartile()
{
    return Adapter.GetProductsWithPriceQuartile();
}

다른 데이터 검색 메서드 ProductsBLLWithSprocs와 마찬가지로 메서드는 GetProductsWithPriceQuartile DAL의 해당 GetProductsWithPriceQuartile 메서드를 호출하고 결과를 반환합니다.

4단계: ASP.NET 웹 페이지에 가격 사분위수 정보 표시

BLL 추가가 완료되면 각 제품의 가격 사분위수로 표시되는 ASP.NET 페이지를 만들 준비가 완료되었습니다. 폴더에서 AddingColumns.aspxAdvancedDAL 페이지를 열고 도구 상자에서 디자이너로 GridView를 끌어 속성을 IDProducts로 설정합니다. GridView의 스마트 태그에서 새 ObjectDataSource ProductsDataSource에 바인딩합니다. ObjectDataSource를 ProductsBLLWithSprocs 클래스의 GetProductsWithPriceQuartile 메서드를 사용하도록 구성합니다. 읽기 전용 표이므로 UPDATE, INSERT 및 DELETE 탭의 드롭다운 목록을 (없음)으로 설정합니다.

ProductsBLLWithSprocs 클래스를 사용하도록 ObjectDataSource 구성

그림 9: 클래스를 사용하도록 ProductsBLLWithSprocs ObjectDataSource 구성(전체 크기 이미지를 보려면 클릭)

GetProductsWithPriceQuartile 메서드에서 제품 정보 검색

그림 10: 메서드에서 GetProductsWithPriceQuartile 제품 정보 검색(전체 크기 이미지를 보려면 클릭)

데이터 원본 구성 마법사를 완료한 후 Visual Studio는 메서드에서 반환된 각 데이터 필드에 대해 GridView에 BoundField 또는 CheckBoxField를 자동으로 추가합니다. 이 데이터 필드들 중 하나는 1단계에서 PriceQuartile에 추가한 ProductsDataTable 열입니다.

GridView의 필드를 편집하여 ProductName, UnitPrice, PriceQuartile BoundFields만 남기고 나머지 모든 필드를 제거합니다. 해당 값의 UnitPrice 형식을 통화로 지정하고 BoundFields와 UnitPricePriceQuartile BoundFields가 각각 오른쪽 및 가운데 맞춤되도록 BoundField를 구성합니다. 마지막으로 나머지 BoundFields HeaderText 속성을 제품, 가격 및 가격 사분위수로 각각 업데이트합니다. 또한 GridView의 스마트 태그에서 정렬 사용 확인란을 선택합니다.

이러한 수정 후에 GridView 및 ObjectDataSource의 선언적 태그는 다음과 같이 표시됩니다.

<asp:GridView ID="Products" runat="server" AllowSorting="True"
    AutoGenerateColumns="False" DataKeyNames="ProductID" 
    DataSourceID="ProductsDataSource">
    <Columns>
        <asp:BoundField DataField="ProductName" HeaderText="Product" 
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" 
            HeaderText="Price" HtmlEncode="False" 
            SortExpression="UnitPrice">
            <ItemStyle HorizontalAlign="Right" />
        </asp:BoundField>
        <asp:BoundField DataField="PriceQuartile" HeaderText="Price Quartile" 
            SortExpression="PriceQuartile">
            <ItemStyle HorizontalAlign="Center" />
        </asp:BoundField>
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProductsWithPriceQuartile" 
    TypeName="ProductsBLLWithSprocs">
</asp:ObjectDataSource>

그림 11은 브라우저를 통해 방문했을 때 이 페이지를 보여줍니다. 처음에는 각 제품에 적절한 PriceQuartile 값이 할당된 내림차순으로 제품이 가격별로 정렬됩니다. 물론 이 데이터는 가격과 관련하여 제품 순위를 반영하는 가격 사분위수 열 값이 있는 다른 기준에 따라 정렬할 수 있습니다(그림 12 참조).

제품은 해당 가격으로 주문됩니다.

그림 11: 제품이 가격별로 정렬됨(전체 크기 이미지를 보려면 클릭)

제품 이름은 해당 이름으로 정렬됩니다.

그림 12: 제품이 이름으로 정렬됨(전체 크기 이미지를 보려면 클릭)

비고

몇 줄의 코드로 GridView를 확장하여 값 PriceQuartile을 기준으로 제품 행에 색을 입힐 수 있습니다. 우리는 첫 번째 사분위수에서 그 제품을 연한 녹색으로, 두 번째 사분위수의 제품은 연한 노란색 등으로 색을 칠할 수 있습니다. 잠시 시간을 내어 이 기능을 추가하는 것이 좋습니다. GridView 서식 지정에 대한 새로 고침이 필요한 경우 데이터 기반 사용자 지정 서식 자습서를 참조하세요.

대체 방법 - 다른 TableAdapter 만들기

이 자습서에서 볼 수 있듯이 기본 쿼리에서 철자가 지정된 필드가 아닌 다른 데이터 필드를 반환하는 TableAdapter에 메서드를 추가할 때 해당 열을 DataTable에 추가할 수 있습니다. 그러나 이러한 접근 방식은 다른 데이터 필드를 반환하는 TableAdapter에 적은 수의 메서드가 있고 이러한 대체 데이터 필드가 주 쿼리와 크게 다르지 않은 경우에만 잘 작동합니다.

DataTable에 열을 추가하는 대신 다른 데이터 필드를 반환하는 첫 번째 TableAdapter의 메서드를 포함하는 다른 TableAdapter를 DataSet에 추가할 수 있습니다. 이 자습서에서는 PriceQuartile 열을 ProductsDataTable(GetProductsWithPriceQuartile 메서드에서만 사용되는) 에 추가하는 대신, ProductsWithPriceQuartileTableAdapter 저장 프로시저를 주요 쿼리로 사용하는 Products_SelectWithPriceQuartile DataSet에 추가적인 TableAdapter를 추가할 수 있었습니다. 가격 사분위수를 포함한 제품 정보를 가져오는데 필요한 ASP.NET 페이지는 ProductsWithPriceQuartileTableAdapter를 사용하고, 그렇지 않은 페이지는 계속해서 ProductsTableAdapter를 사용할 수 있습니다.

새 TableAdapter를 추가하면 DataTable은 변형 없이 유지되고, 해당 열은 TableAdapter 메서드에서 반환된 데이터 필드를 정확하게 반영합니다. 그러나 추가 TableAdapters는 반복적인 작업 및 기능을 도입할 수 있습니다. 예를 들어, 열을 표시한 PriceQuartile ASP.NET 페이지에서도 삽입, 업데이트 및 삭제 지원을 제공해야 한다면, ProductsWithPriceQuartileTableAdapter에는 InsertCommand, UpdateCommand, DeleteCommand 속성을 올바르게 구성해야 합니다. 이러한 속성은 s를 ProductsTableAdapter 미러링하지만 이 구성에는 추가 단계가 도입됩니다. 또한 이제 데이터베이스 및 ProductsTableAdapter 클래스를 통해 ProductsWithPriceQuartileTableAdapter 제품을 업데이트, 삭제 또는 데이터베이스에 추가하는 두 가지 방법이 있습니다.

이 자습서의 다운로드에는 이 대체 방법을 보여 주는 ProductsWithPriceQuartileTableAdapter 클래스가 NorthwindWithSprocs DataSet에 포함되어 있습니다.

요약

대부분의 시나리오에서 TableAdapter의 모든 메서드는 동일한 데이터 필드 집합을 반환하지만 특정 메서드 또는 두 메서드가 추가 필드를 반환해야 하는 경우가 있습니다. 예를 들어 세부 정보 DataList 자습서와 함께 마스터 레코드의 글머리 기호 목록을 사용하여 마스터/세부 정보에서 기본 쿼리의 데이터 필드 외에도 각 범주와 연결된 제품 수를 보고하는 필드를 반환 CategoriesTableAdapter 하는 메서드 NumberOfProducts 를 추가했습니다. 이 자습서에서는 기본 쿼리의 데이터 필드 외에도 필드를 반환하는 ProductsTableAdapter 메서드 PriceQuartile 를 추가하는 방법을 살펴보았습니다. TableAdapter 메서드에서 반환된 추가 데이터 필드를 캡처하려면 해당 열을 DataTable에 추가해야 합니다.

DataTable에 열을 수동으로 추가하려는 경우 TableAdapter에서 저장 프로시저를 사용하는 것이 좋습니다. TableAdapter에서 임시 SQL 문을 사용하는 경우 TableAdapter 구성 마법사가 실행될 때마다 모든 메서드 데이터 필드 목록이 주 쿼리에서 반환된 데이터 필드로 되돌아갑니다. 이 문제는 저장 프로시저로 확장되지 않으므로 권장되며 이 자습서에서 사용되었습니다.

행복한 프로그래밍!

작성자 정보

7개의 ASP/ASP.NET 책의 저자이자 4GuysFromRolla.com 창립자인 Scott Mitchell은 1998년부터 Microsoft 웹 기술을 연구해 왔습니다. Scott은 독립 컨설턴트, 트레이너 및 작가로 일합니다. 그의 최신 책은 샘스 Teach Yourself ASP.NET 2.0 24시간 안에입니다. 그에게 mitchell@4GuysFromRolla.com으로 연락할 수 있습니다.

특별히 감사드립니다.

이 자습서 시리즈는 많은 유용한 검토자가 검토했습니다. 이 자습서의 수석 검토자는 랜디 슈미트, 재키 구어, 버나데트 리, 힐튼 기제나우였습니다. 예정된 MSDN 문서를 검토하는 데 관심이 있으신가요? 그렇다면 mitchell@4GuysFromRolla.com으로 메시지를 보내 주세요.