다음을 통해 공유


일괄 업데이트(VB)

스콧 미첼

PDF 다운로드

단일 작업에서 여러 데이터베이스 레코드를 업데이트하는 방법을 알아봅니다. 사용자 인터페이스 계층에서 각 행을 편집할 수 있는 GridView를 빌드합니다. 데이터 액세스 계층에서 트랜잭션 내에서 여러 업데이트 작업을 래핑하여 모든 업데이트가 성공하거나 모든 업데이트가 롤백되도록 합니다.

소개

이전 자습서에서는 데이터 액세스 계층을 확장하여 데이터베이스 트랜잭션에 대한 지원을 추가하는 방법을 알아보았습니다. 데이터베이스 트랜잭션은 일련의 데이터 수정 문을 하나의 원자성 연산으로 처리하여 모든 수정이 실패하거나 모두 성공하도록 보장합니다. 이 하위 수준 DAL 기능을 사용하면 일괄 처리 데이터 수정 인터페이스를 만드는 데 주의를 기울일 준비가 된 것입니다.

이 자습서에서는 각 행을 편집할 수 있는 GridView를 빌드합니다(그림 1 참조). 각 행은 편집 인터페이스에서 렌더링되므로 편집, 업데이트 및 취소 단추 열이 필요하지 않습니다. 대신 페이지에는 GridView 행을 열거하고 데이터베이스를 업데이트하는 두 개의 제품 업데이트 단추가 있습니다.

GridView의 각 행은 편집 가능

그림 1: GridView의 각 행을 편집할 수 있습니다(전체 크기 이미지를 보려면 클릭).

시작해 보겠습니다!

참고 항목

Batch 업데이트 수행 자습서에서는 DataList 컨트롤을 사용하여 일괄 처리 편집 인터페이스를 만들었습니다. 이 자습서는 GridView를 사용하고 일괄 업데이트가 트랜잭션 범위 내에서 수행된다는 점에서 이전 자습서와 다릅니다. 이 자습서를 완료한 후 이전 자습서로 돌아가서 이전 자습서에 추가된 데이터베이스 트랜잭션 관련 기능을 사용하도록 업데이트하는 것이 좋습니다.

모든 GridView 행을 편집 가능하게 만드는 단계 검사

데이터 삽입, 업데이트 및 삭제 개요에 설명된 대로 GridView는 행별로 기본 데이터 편집을 기본적으로 지원합니다. 내부적으로 GridView는 속성을 통해 편집할 수 있는 행을 설명합니다.EditIndex GridView는 데이터 원본에 바인딩되므로 각 행을 확인하여 행의 인덱스가 값 EditIndex과 같은지 확인합니다. 이 경우 해당 행의 필드는 편집 인터페이스를 사용하여 렌더링됩니다. BoundFields의 경우 편집 인터페이스는 속성에 Text BoundField 속성으로 지정된 데이터 필드의 값이 할당된 TextBox입니다 DataField . TemplateFields의 경우 .EditItemTemplate ItemTemplate

사용자가 행의 편집 단추를 클릭하면 편집 워크플로가 시작됩니다. 이렇게 하면 포스트백이 발생하고 GridView의 EditIndex 속성이 클릭한 행의 인덱스로 설정되고 데이터가 그리드에 다시 바인딩됩니다. 행의 취소 단추를 클릭하면 포스트백 EditIndex 시 데이터를 그리드에 다시 바인딩하기 전에 값 -1 으로 설정됩니다. GridView의 행은 0에서 인덱싱을 시작하므로 -1 읽기 EditIndex 전용 모드로 GridView를 표시하는 효과가 적용됩니다.

이 속성은 EditIndex 행별 편집에 적합하지만 일괄 편집용으로 설계되지 않았습니다. 전체 GridView를 편집할 수 있도록 하려면 편집 인터페이스를 사용하여 각 행을 렌더링해야 합니다. 이 작업을 수행하는 가장 쉬운 방법은 편집 가능한 각 필드가 편집 인터페이스가 정의된 ItemTemplateTemplateField로 구현되는 위치를 만드는 것입니다.

다음 몇 단계를 통해 완전히 편집 가능한 GridView를 만듭니다. 1단계에서는 GridView 및 ObjectDataSource를 만들고 BoundFields 및 CheckBoxField를 TemplateFields로 변환합니다. 2단계와 3단계에서는 편집 인터페이스를 TemplateFields EditItemTemplate 에서 해당 ItemTemplate 인터페이스로 이동합니다.

1단계: 제품 정보 표시

행을 편집할 수 있는 GridView를 만드는 것에 대해 걱정하기 전에 제품 정보를 표시하기만 하면 됩니다. 폴더에서 BatchUpdate.aspx BatchData 페이지를 열고 도구 상자에서 디자이너로 GridView를 끕니다. GridView ID ProductsGrid 를 스마트 태그로 설정하고 해당 태그를 새 ObjectDataSource에 ProductsDataSource바인딩하도록 선택합니다. 클래스의 GetProducts 메서드에서 해당 데이터를 검색하도록 ObjectDataSource를 ProductsBLL 구성합니다.

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

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

GetProducts 메서드를 사용하여 제품 데이터 검색

그림 3: 메서드를 사용하여 GetProducts 제품 데이터 검색(전체 크기 이미지를 보려면 클릭)

GridView와 마찬가지로 ObjectDataSource의 수정 기능은 행별로 작동하도록 설계되었습니다. 레코드 집합을 업데이트하려면 데이터를 일괄 처리하고 BLL에 전달하는 ASP.NET 페이지의 코드 숨김 클래스에 약간의 코드를 작성해야 합니다. 따라서 ObjectDataSource의 UPDATE, INSERT 및 DELETE 탭의 드롭다운 목록을 (없음)으로 설정합니다. 마침을 클릭하여 마법사를 완료합니다.

UPDATE, INSERT 및 DELETE 탭의 드롭다운 목록을 (없음)으로 설정

그림 4: UPDATE, INSERT 및 DELETE 탭의 드롭다운 목록을 (없음)으로 설정합니다(전체 크기 이미지를 보려면 클릭).

데이터 원본 구성 마법사를 완료한 후 ObjectDataSource의 선언적 태그는 다음과 같습니다.

<asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProducts" TypeName="ProductsBLL">
</asp:ObjectDataSource>

데이터 원본 구성 마법사를 완료하면 Visual Studio에서 GridView의 제품 데이터 필드에 대한 BoundFields 및 CheckBoxField를 만들 수도 있습니다. 이 자습서에서는 사용자가 제품 이름, 범주, 가격 및 중단된 상태를 보고 편집할 수 있도록 허용해 보겠습니다. , , 및 필드를 제외한 ProductName모든 필드를 제거하고 처음 세 필드의 속성 이름을 각각 Product, Category 및 Price로 바꿉 HeaderText 니다.Discontinued UnitPriceCategoryName 마지막으로 GridView의 스마트 태그에서 페이징 사용 및 정렬 사용 확인란을 선택합니다.

이 시점에서 GridView에는 세 개의 BoundField(ProductName, CategoryName및) 및 UnitPriceCheckBoxField(Discontinued)가 있습니다. 이러한 4개의 필드를 TemplateFields로 변환한 다음, 편집 인터페이스를 TemplateField에서 EditItemTemplate 해당 필드로 이동해야 합니다 ItemTemplate.

참고 항목

데이터 수정 인터페이스 사용자 지정 자습서에서 TemplateFields를 만들고 사용자 지정하는 방법을 살펴보했습니다. BoundFields 및 CheckBoxField를 TemplateFields로 변환하고 편집 인터페이스 ItemTemplate 를 정의하는 단계를 안내하지만, 중단되거나 새로 고침이 필요한 경우 이 이전 자습서를 다시 참조하세요.

GridView의 스마트 태그에서 열 편집 링크를 클릭하여 필드 대화 상자를 엽니다. 다음으로, 각 필드를 선택하고 이 필드를 TemplateField 링크로 변환을 클릭합니다.

기존 BoundFields 및 CheckBoxField를 TemplateFields로 변환

그림 5: 기존 BoundFields 및 CheckBoxField를 TemplateFields로 변환

이제 각 필드가 TemplateField이므로 편집 인터페이스를 s에서 EditItemTemplate ItemTemplate s로 이동할 준비가 되었습니다.

2단계: 인터페이스 만들기ProductNameUnitPriceDiscontinued편집

각 인터페이스가 UnitPriceProductNameTemplateField에 이미 정의되어 있으므로 , 및 Discontinued 편집 인터페이스를 만드는 것은 이 단계의 EditItemTemplate항목이며 매우 간단합니다. 해당 범주의 CategoryName DropDownList를 만들어야 하므로 편집 인터페이스를 만드는 것이 좀 더 복잡합니다. 이 CategoryName 편집 인터페이스는 3단계에서 해결됩니다.

TemplateField부터 ProductName 시작해 보겠습니다. GridView의 스마트 태그에서 템플릿 편집 링크를 클릭하고 TemplateFieldEditItemTemplate로 드릴다운 ProductName 합니다. TextBox를 선택하고 클립보드에 복사한 다음 TemplateField에 ProductName 붙여넣습니다 ItemTemplate. TextBox 속성을 ID ProductName.로 변경합니다.

다음으로 RequiredFieldValidator를 ItemTemplate 추가하여 사용자가 각 제품 이름에 대한 값을 제공하는지 확인합니다. ControlToValidate 속성을 ProductName으로 설정합니다. 이 속성은 ErrorMessage 제품의 이름을 제공해야 합니다. 및 속성을 Text *로 지정합니다. 이러한 추가 작업을 수행한 후 화면은 ItemTemplate그림 6과 유사하게 표시됩니다.

ProductName TemplateField에는 이제 TextBox 및 RequiredFieldValidator가 포함됩니다.

그림 6: ProductName 이제 TemplateField에 TextBox 및 RequiredFieldValidator가 포함되어 있습니다(전체 크기 이미지를 보려면 클릭).

편집 인터페이스의 UnitPrice 경우 먼저 TextBox를 다음으로 EditItemTemplate 복사합니다 ItemTemplate. 다음으로 TextBox 앞에 $를 놓고 해당 ID 속성을 UnitPrice로 설정하고 해당 Columns 속성을 8로 설정합니다.

또한 CompareValidator를 UnitPrice ItemTemplate 추가하여 사용자가 입력한 값이 $0.00보다 크거나 같은 유효한 통화 값인지 확인합니다. 유효성 검사기의 ControlToValidate 속성을 UnitPrice로 설정합니다. 이 ErrorMessage 속성은 유효한 통화 값을 입력해야 합니다. 통화 기호를 생략하십시오., *에 대한 속성 Text , 해당 Type 속성에 대한 Currency속성, 해당 Operator 속성 GreaterThanEqual에 대한 속성 및 해당 ValueToCompare 속성은 0으로 생략하십시오.

CompareValidator를 추가하여 입력한 가격이 음수가 아닌 통화 값인지 확인합니다.

그림 7: CompareValidator를 추가하여 입력한 가격이 음수가 아닌 통화 값인지 확인합니다(전체 크기 이미지를 보려면 클릭).

TemplateField의 Discontinued 경우 에 이미 정의된 CheckBox를 ItemTemplate사용할 수 있습니다. 간단히 해당 속성을 ID Discontinued로 설정하고 해당 Enabled 속성을 .로 True설정합니다.

3단계: 편집 인터페이스 만들기CategoryName

TemplateField의 EditItemTemplate 편집 인터페이스 CategoryName 에는 데이터 필드의 값을 표시하는 TextBox가 CategoryName 포함되어 있습니다. 가능한 범주를 나열하는 DropDownList로 바꿔야 합니다.

참고 항목

데이터 수정 인터페이스 사용자 지정 자습서에는 TextBox가 아닌 DropDownList를 포함하도록 템플릿을 사용자 지정하는 방법에 대한 보다 철저하고 완전한 설명이 포함되어 있습니다. 이 단계가 완료된 동안에는 세세하게 표시됩니다. DropDownList 범주를 만들고 구성하는 방법에 대한 자세한 내용은 데이터 수정 인터페이스 사용자 지정 자습서를 참조하세요.

Toolbox에서 TemplateField로 DropDownList를 CategoryName 끌어서 설정합니다 ID Categories.ItemTemplate 이 시점에서 일반적으로 스마트 태그를 통해 DropDownLists의 데이터 원본을 정의하여 새 ObjectDataSource를 만듭니다. 그러나 그러면 ObjectDataSource가 추가 ItemTemplate됩니다. 그러면 각 GridView 행에 대해 ObjectDataSource 인스턴스가 만들어집니다. 대신 GridView의 TemplateFields 외부에서 ObjectDataSource를 만들어 보겠습니다. 템플릿 편집을 종료하고 Toolbox에서 ObjectDataSource 아래의 디자이너로 ObjectDataSource를 ProductsDataSource 끕니다. 새 ObjectDataSource CategoriesDataSource 의 이름을 지정하고 클래스의 GetCategories 메서드를 CategoriesBLL 사용하도록 구성합니다.

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

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

GetCategories 메서드를 사용하여 범주 데이터 검색

그림 9: 메서드를 사용하여 GetCategories 범주 데이터 검색(전체 크기 이미지를 보려면 클릭)

이 ObjectDataSource는 데이터를 검색하는 데만 사용되므로 UPDATE 및 DELETE 탭의 드롭다운 목록을 (없음)으로 설정합니다. 마침을 클릭하여 마법사를 완료합니다.

UPDATE 및 DELETE 탭의 드롭다운 목록을 (없음)으로 설정

그림 10: UPDATE 및 DELETE 탭의 드롭다운 목록을 (없음)으로 설정(전체 크기 이미지를 보려면 클릭)

마법사 CategoriesDataSource 를 완료한 후 선언적 태그는 다음과 같이 표시됩니다.

<asp:ObjectDataSource ID="CategoriesDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

만들고 구성한 CategoriesDataSource 상태에서 TemplateField로 CategoryName ItemTemplate 돌아가서 DropDownList의 스마트 태그에서 데이터 원본 선택 링크를 클릭합니다. 데이터 원본 구성 마법사의 CategoriesDataSource 첫 번째 드롭다운 목록에서 옵션을 선택하고 표시 CategoryID 및 값으로 사용하도록 선택합니다CategoryName.

CategoriesDataSource에 DropDownList 바인딩

그림 11: DropDownList를 바인딩합니다 CategoriesDataSource (전체 크기 이미지를 보려면 클릭).

이 시점에서 Categories DropDownList는 모든 범주를 나열하지만 GridView 행에 바인딩된 제품에 적합한 범주를 아직 자동으로 선택하지는 않습니다. 이렇게 하려면 DropDownList SelectedValueCategories 제품 CategoryID 값으로 설정해야 합니다. DropDownList의 스마트 태그에서 DataBindings 편집 링크를 클릭하고 그림 12와 같이 속성을 데이터 필드와 CategoryID 연결 SelectedValue 합니다.

DropDownList의 SelectedValue 속성에 제품의 CategoryID 값 바인딩

그림 12: DropDownList의 CategoryID SelectedValue 속성에 제품 값 바인딩

마지막 문제 중 하나는 제품에 지정된 값이 CategoryID 없는 경우 databinding 문이 SelectedValue 예외를 발생시키는 것입니다. DropDownList는 범주에 대한 항목만 포함하고 데이터베이스 값이 NULL 있는 제품에 대한 옵션을 제공하지 않기 때문 CategoryID입니다. 이 문제를 해결하려면 DropDownList의 AppendDataBoundItems 속성을 True 설정하고 DropDownList에 새 항목을 추가하여 선언적 구문에서 속성을 생략 Value 합니다. 즉, DropDownList의 선언적 구문이 다음과 같은지 확인 Categories 합니다.

<asp:DropDownList ID="Categories" runat="server" AppendDataBoundItems="True" 
    DataSourceID="CategoriesDataSource" DataTextField="CategoryName" 
    DataValueField="CategoryID" SelectedValue='<%# Bind("CategoryID") %>'>
    <asp:ListItem Value=">-- Select One --</asp:ListItem>
</asp:DropDownList>

Select One의 특성이 Value 빈 문자열로 명시적으로 설정된 방법을 <asp:ListItem Value=""> 확인합니다. 사례를 처리하는 NULL이 추가 DropDownList 항목이 필요한 이유와 빈 문자열에 속성을 할당 Value 하는 것이 중요한 이유에 대한 자세한 내용은 데이터 수정 인터페이스 사용자 지정 자습서를 참조하세요.

참고 항목

여기에 언급할 만한 잠재적인 성능 및 확장성 문제가 있습니다. 각 행에는 데이터 원본으로 사용하는 CategoriesDataSource DropDownList가 있으므로 클래스의 GetCategories 메서드는 페이지 방문당 n번 호출됩니다. 여기서 n은 GridView의 행 수 CategoriesBLL 입니다. 이러한 n 호출은 GetCategories 데이터베이스에 대한 n 개의 쿼리를 생성합니다. SQL 캐싱 종속성 또는 매우 짧은 시간 기반 만료를 사용하여 요청당 캐시 또는 캐싱 계층을 통해 반환된 범주를 캐싱하여 데이터베이스에 미치는 영향을 줄일 수 있습니다.

4단계: 편집 인터페이스 완료

진행 상황을 보기 위해 잠시 멈추지 않고 GridView 템플릿을 여러 번 변경했습니다. 잠시 브라우저를 통해 진행 상황을 확인하세요. 그림 13과 같이 각 행은 셀의 편집 인터페이스를 포함하는 행을 사용하여 ItemTemplate렌더링됩니다.

각 GridView 행은 편집 가능

그림 13: 각 GridView 행을 편집할 수 있습니다(전체 크기 이미지를 보려면 클릭).

이 시점에서 처리해야 하는 몇 가지 사소한 서식 문제가 있습니다. 먼저 값에 UnitPrice 소수점 4개가 포함됩니다. 이 문제를 해결하려면 TemplateField로 UnitPrice ItemTemplate 돌아가서 TextBox의 스마트 태그에서 DataBindings 편집 링크를 클릭합니다. 다음으로 속성의 서식을 Text 숫자로 지정합니다.

Text 속성의 서식을 숫자로 지정

그림 14: 속성 형식을 Text 숫자로 지정

둘째, 확인란을 왼쪽 맞춤이 아닌 열의 Discontinued 가운데에 배치해 보겠습니다. GridView의 스마트 태그에서 열 편집을 클릭하고 왼쪽 아래 모서리에 있는 필드 목록에서 TemplateField를 선택합니다 Discontinued . 그림 15와 ItemStyle 같이 속성을 드릴다운하고 가운데로 설정합니다 HorizontalAlign .

중단된 확인란 가운데 맞춤

그림 15: 확인란 가운데 맞춤 Discontinued

다음으로, 페이지에 ValidationSummary 컨트롤을 추가하고 해당 속성과 해당 ShowMessageBox ShowSummary 속성을 True False.로 설정합니다. 또한 단추 웹 컨트롤을 추가합니다. 이 컨트롤을 클릭하면 사용자의 변경 내용이 업데이트됩니다. 특히 두 개의 Button Web 컨트롤을 추가합니다. 하나는 GridView 위에, 다른 하나는 아래에 추가되며, 두 컨트롤 Text 속성을 모두 제품 업데이트로 설정합니다.

GridView의 편집 인터페이스는 TemplateFields ItemTemplate EditItemTemplate 에 정의되므로 s는 불필요하며 삭제될 수 있습니다.

위에서 언급한 서식 변경, 단추 컨트롤 추가 및 불필요한 EditItemTemplate 항목을 제거한 후 페이지의 선언적 구문은 다음과 같이 표시됩니다.

<p>
    <asp:Button ID="UpdateAllProducts1" runat="server" Text="Update Products" />
</p>
<p>
    <asp:GridView ID="ProductsGrid" runat="server" AutoGenerateColumns="False" 
        DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
        AllowPaging="True" AllowSorting="True">
        <Columns>
            <asp:TemplateField HeaderText="Product" SortExpression="ProductName">
                <ItemTemplate>
                    <asp:TextBox ID="ProductName" runat="server" 
                        Text='<%# Bind("ProductName") %>'></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" 
                        ControlToValidate="ProductName"
                        ErrorMessage="You must provide the product's name." 
                        runat="server">*</asp:RequiredFieldValidator>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Category" 
                SortExpression="CategoryName">
                <ItemTemplate>
                    <asp:DropDownList ID="Categories" runat="server" 
                        AppendDataBoundItems="True" 
                        DataSourceID="CategoriesDataSource"
                        DataTextField="CategoryName" 
                        DataValueField="CategoryID" 
                        SelectedValue='<%# Bind("CategoryID") %>'>
                        <asp:ListItem>-- Select One --</asp:ListItem>
                    </asp:DropDownList>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Price" 
                SortExpression="UnitPrice">
                <ItemTemplate>
                    $<asp:TextBox ID="UnitPrice" runat="server" Columns="8" 
                        Text='<%# Bind("UnitPrice", "{0:N}") %>'></asp:TextBox>
                    <asp:CompareValidator ID="CompareValidator1" runat="server" 
                        ControlToValidate="UnitPrice"
                        ErrorMessage="You must enter a valid currency value. 
                                      Please omit any currency symbols."
                        Operator="GreaterThanEqual" Type="Currency" 
                        ValueToCompare="0">*</asp:CompareValidator>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
                <ItemTemplate>
                    <asp:CheckBox ID="Discontinued" runat="server" 
                        Checked='<%# Bind("Discontinued") %>' />
                </ItemTemplate>
                <ItemStyle HorizontalAlign="Center" />
            </asp:TemplateField>
        </Columns>
    </asp:GridView>
</p>
<p>
    <asp:Button ID="UpdateAllProducts2" runat="server" Text="Update Products" />
    <asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
        OldValuesParameterFormatString="original_{0}"
        SelectMethod="GetProducts" TypeName="ProductsBLL">
    </asp:ObjectDataSource>
    <asp:ObjectDataSource ID="CategoriesDataSource" runat="server" 
        OldValuesParameterFormatString="original_{0}"
        SelectMethod="GetCategories" TypeName="CategoriesBLL">
    </asp:ObjectDataSource>
    <asp:ValidationSummary ID="ValidationSummary1" runat="server" 
        ShowMessageBox="True" ShowSummary="False" />
</p>

그림 16에서는 단추 웹 컨트롤이 추가되고 서식이 변경된 후 브라우저를 통해 볼 때 이 페이지를 보여 줍니다.

이제 페이지에 두 개의 업데이트 제품 단추가 포함됩니다.

그림 16: 이제 페이지에 두 개의 업데이트 제품 단추가 포함되어 있습니다(전체 크기 이미지를 보려면 클릭).

5단계: 제품 업데이트

사용자가 이 페이지를 방문하면 수정한 다음 두 가지 제품 업데이트 단추 중 하나를 클릭합니다. 이 시점에서 각 행에 대해 사용자가 입력한 값을 인스턴스에 ProductsDataTable 저장한 다음 해당 인스턴스를 DAL UpdateWithTransaction 메서드에 전달하는 BLL 메서드에 전달 ProductsDataTable 해야 합니다. 이전 자습서에서 만든 메서드는 UpdateWithTransaction 변경 내용의 일괄 처리가 원자성 작업으로 업데이트되도록 합니다.

명명 BatchUpdate BatchUpdate.aspx.vb 된 메서드를 만들고 다음 코드를 추가합니다.

Private Sub BatchUpdate()
    ' Enumerate the GridView's Rows collection and create a ProductRow
    Dim productsAPI As New ProductsBLL()
    Dim products As Northwind.ProductsDataTable = productsAPI.GetProducts()
    For Each gvRow As GridViewRow In ProductsGrid.Rows
        ' Find the ProductsRow instance in products that maps to gvRow
        Dim productID As Integer = _
            Convert.ToInt32(ProductsGrid.DataKeys(gvRow.RowIndex).Value)
        Dim product As Northwind.ProductsRow = products.FindByProductID(productID)
        If product IsNot Nothing Then
            ' Programmatically access the form field elements in the 
            ' current GridViewRow
            Dim productName As TextBox = _
                CType(gvRow.FindControl("ProductName"), TextBox)
            Dim categories As DropDownList = _
                CType(gvRow.FindControl("Categories"), DropDownList)
            Dim unitPrice As TextBox = _
                CType(gvRow.FindControl("UnitPrice"), TextBox)
            Dim discontinued As CheckBox = _
                CType(gvRow.FindControl("Discontinued"), CheckBox)
            ' Assign the user-entered values to the current ProductRow
            product.ProductName = productName.Text.Trim()
            If categories.SelectedIndex = 0 Then 
                product.SetCategoryIDNull() 
            Else 
                product.CategoryID = Convert.ToInt32(categories.SelectedValue)
            End If
            If unitPrice.Text.Trim().Length = 0 Then 
                product.SetUnitPriceNull() 
            Else 
                product.UnitPrice = Convert.ToDecimal(unitPrice.Text)
            End If
            product.Discontinued = discontinued.Checked
        End If
    Next
    ' Now have the BLL update the products data using a transaction
    productsAPI.UpdateWithTransaction(products)
End Sub

이 메서드는 BLL GetProducts 메서드에 대한 호출을 ProductsDataTable 통해 모든 제품을 다시 가져오는 것으로 시작합니다. 그런 다음 GridView의 Rows 컬렉션을 열거합니다ProductGrid. 컬렉션에는 Rows GridViewRow GridView에 표시되는 각 행에 대한 인스턴스 가 포함됩니다. 페이지당 최대 10개의 행을 표시하므로 GridView 컬렉션에는 10개 이하의 Rows 항목이 있습니다.

각 행에 대해 ProductID 컬렉션에서 해당 행을 DataKeys 가져오고 해당 ProductsRow 행을 선택합니다 ProductsDataTable. 네 개의 TemplateField 입력 컨트롤이 프로그래밍 방식으로 참조되고 해당 값이 인스턴스의 속성에 ProductsRow 할당됩니다. 각 GridView 행의 값을 업데이트ProductsDataTable하는 데 사용한 후에는 이전 자습서에서 보았듯이 DAL UpdateWithTransaction 메서드를 호출하기만 하면 되는 BLL UpdateWithTransaction 메서드로 전달됩니다.

이 자습서에 사용되는 일괄 업데이트 알고리즘은 제품 정보가 변경되었는지 여부에 관계없이 GridView의 행에 해당하는 각 행 ProductsDataTable 을 업데이트합니다. 이러한 블라인드 업데이트는 일반적으로 성능 문제가 아니지만 데이터베이스 테이블의 변경 내용을 감사하는 경우 불필요한 레코드로 이어질 수 있습니다. Batch 업데이트 수행 자습서에서 DataList를 사용하여 일괄 업데이트 인터페이스를 탐색하고 사용자가 실제로 수정한 레코드만 업데이트하는 코드를 추가했습니다. 원하는 경우 Batch 업데이트를 수행하여 이 자습서의 코드를 업데이트하는 기술을 자유롭게 사용할 수 있습니다.

참고 항목

스마트 태그를 통해 데이터 원본을 GridView에 바인딩하는 경우 Visual Studio는 자동으로 데이터 원본의 기본 키 값을 GridView의 DataKeyNames 속성에 할당합니다. 1단계에 설명된 대로 GridView의 스마트 태그를 통해 GridView에 ObjectDataSource를 바인딩하지 않은 경우 컬렉션을 통해 DataKeys 각 행의 값에 액세스 ProductID 하기 위해 GridView 속성을 DataKeyNames ProductID로 수동으로 설정해야 합니다.

사용된 BatchUpdate 코드는 BLL UpdateProduct 메서드에서 사용되는 코드와 유사하며, 주요 차이점은 메서드에서 아키텍처에서 UpdateProduct 단일 ProductRow 인스턴스만 검색된다는 점입니다. 해당 속성을 ProductRow 할당하는 코드는 전체 패턴과 마찬가지로 루프 BatchUpdateFor Each 의 메서드와 코드 간에 UpdateProducts 동일합니다.

이 자습서를 완료하려면 제품 업데이트 단추 중 하나를 클릭할 BatchUpdate 때 메서드를 호출해야 합니다. 이러한 두 Button 컨트롤의 이벤트에 대한 Click 이벤트 처리기를 만들고 이벤트 처리기에 다음 코드를 추가합니다.

BatchUpdate()
ClientScript.RegisterStartupScript(Me.GetType(), "message", _
    "alert('The products have been updated.');", True)

먼저 호출이 이루어집니다 BatchUpdate. 다음으로, ClientScript 이 속성 은 제품이 업데이트되었음을 읽는 메시지 상자를 표시하는 JavaScript를 삽입하는 데 사용됩니다.

이 코드를 테스트하는 데 1분 정도 걸릴 수 있습니다. 브라우저를 통해 방문하여 BatchUpdate.aspx 여러 행을 편집하고 제품 업데이트 단추 중 하나를 클릭합니다. 입력 유효성 검사 오류가 없다고 가정하면 제품이 업데이트되었음을 읽는 메시지 상자가 표시됩니다. 업데이트의 원자성을 확인하려면 1234.56 값을 허용하지 UnitPrice 않는 것과 같은 임 CHECK 의 제약 조건을 추가하는 것이 좋습니다. 그런 다음, BatchUpdate.aspx여러 레코드를 편집하여 제품 UnitPrice 값 중 하나를 금지된 값(1234.56)으로 설정해야 합니다. 이렇게 하면 일괄 처리 작업 중에 다른 변경 내용이 포함된 제품 업데이트를 클릭하면 원래 값으로 롤백되는 오류가 발생합니다.

대체BatchUpdate메서드

방금 검사한 메서드는 BatchUpdate BLL GetProducts 메서드에서 모든 제품을 검색한 다음 GridView에 표시되는 레코드만 업데이트합니다. 이 방법은 GridView가 페이징을 사용하지 않는 경우에 이상적이지만, 이 경우 수백, 수천 또는 수만 개의 제품이 있을 수 있지만 GridView에는 10개의 행만 있을 수 있습니다. 이러한 경우 데이터베이스에서 10개만 수정하기 위해 모든 제품을 가져오는 것이 이상적이지 않습니다.

이러한 유형의 경우 다음 BatchUpdateAlternate 메서드를 대신 사용하는 것이 좋습니다.

Private Sub BatchUpdateAlternate()
    ' Enumerate the GridView's Rows collection and create a ProductRow
    Dim productsAPI As New ProductsBLL()
    Dim products As New Northwind.ProductsDataTable()
    For Each gvRow As GridViewRow In ProductsGrid.Rows
        ' Create a new ProductRow instance
        Dim productID As Integer = _
            Convert.ToInt32(ProductsGrid.DataKeys(gvRow.RowIndex).Value)
        Dim currentProductDataTable As Northwind.ProductsDataTable = _
            productsAPI.GetProductByProductID(productID)
        If currentProductDataTable.Rows.Count > 0 Then
            Dim product As Northwind.ProductsRow = currentProductDataTable(0)
            Dim productName As TextBox = _
                CType(gvRow.FindControl("ProductName"), TextBox)
            Dim categories As DropDownList = _
                CType(gvRow.FindControl("Categories"), DropDownList)
            Dim unitPrice As TextBox = _
                CType(gvRow.FindControl("UnitPrice"), TextBox)
            Dim discontinued As CheckBox = _
                CType(gvRow.FindControl("Discontinued"), CheckBox)
            ' Assign the user-entered values to the current ProductRow
            product.ProductName = productName.Text.Trim()
            If categories.SelectedIndex = 0 Then 
                product.SetCategoryIDNull() 
            Else 
                product.CategoryID = Convert.ToInt32(categories.SelectedValue)
            End If
            If unitPrice.Text.Trim().Length = 0 Then 
                product.SetUnitPriceNull() 
            Else 
                product.UnitPrice = Convert.ToDecimal(unitPrice.Text)
            End If
            product.Discontinued = discontinued.Checked
            ' Import the ProductRow into the products DataTable
            products.ImportRow(product)
        End If
    Next
    ' Now have the BLL update the products data using a transaction
    productsAPI.UpdateProductsWithTransaction(products)
End Sub

BatchMethodAlternate 는 비어 있는 새 ProductsDataTable 이름을 products만들어 시작합니다. 그런 다음 GridView 컬렉션을 Rows 단계별로 실행하고 각 행에 대해 BLL 메서드 GetProductByProductID(productID) 를 사용하여 특정 제품 정보를 가져옵니다. 검색된 ProductsRow 인스턴스의 속성은 동일한 BatchUpdate방식으로 업데이트되지만 행을 업데이트한 ProductsDataTable products 후에는 DataTable 메서드ImportRow(DataRow)를 통해 가져옵니다.

루프가 For Each 완료되면 products GridView의 각 행에 대해 하나의 ProductsRow 인스턴스를 포함합니다. 각 인스턴스가 ProductsRow 업데이트 대신에 추가 products 되었으므로 메서드 ProductsTableAdapter 에 맹목적으로 전달 UpdateWithTransaction 하면 각 레코드를 데이터베이스에 삽입하려고 합니다. 대신 이러한 각 행이 수정되었음을 지정해야 합니다(추가되지 않음).

이 작업은 명명 UpdateProductsWithTransaction된 BLL에 새 메서드를 추가하여 수행할 수 있습니다. UpdateProductsWithTransaction아래와 같이 to의 각 인스턴스 ProductsDataTable 를 설정한 RowState 다음 DAL UpdateWithTransaction 메서드에 전달합니다ProductsDataTable.Modified ProductsRow

Public Function UpdateProductsWithTransaction _
    (ByVal products As Northwind.ProductsDataTable) As Integer
    ' Mark each product as Modified
    products.AcceptChanges()
    For Each product As Northwind.ProductsRow In products
        product.SetModified()
    Next
    ' Update the data via a transaction
    Return UpdateWithTransaction(products)
End Function

요약

GridView는 행당 기본 제공 편집 기능을 제공하지만 완전히 편집 가능한 인터페이스를 만들 수 있는 지원은 없습니다. 이 자습서에서 보았듯이 이러한 인터페이스는 가능하지만 약간의 작업이 필요합니다. 모든 행을 편집할 수 있는 GridView를 만들려면 GridView 필드를 TemplateFields로 변환하고 편집 인터페이스를 ItemTemplate 정의해야 합니다. 또한 모든 형식의 업데이트 단추 웹 컨트롤을 GridView와 별도로 페이지에 추가해야 합니다. 이러한 Buttons Click 이벤트 처리기는 GridView 컬렉션을 Rows 열거하고, 변경 내용을 ProductsDataTable저장하고, 업데이트된 정보를 적절한 BLL 메서드에 전달해야 합니다.

다음 자습서에서는 일괄 처리 삭제를 위한 인터페이스를 만드는 방법을 알아보세요. 특히 각 GridView 행에는 확인란이 포함되며 모든 형식 업데이트 단추 대신 선택한 행 삭제 단추가 있습니다.

행복한 프로그래밍!

작성자 정보

7개의 ASP/ASP.NET 책의 저자이자 4GuysFromRolla.com 창립자인 Scott Mitchell은 1998년부터 Microsoft 웹 기술을 연구해 왔습니다. Scott은 독립 컨설턴트, 트레이너 및 작가로 일합니다. 그의 최신 책은 샘스 티치 자신 ASP.NET 24 시간에 2.0입니다. 그는 에서 mitchell@4GuysFromRolla.com찾을 http://ScottOnWriting.NET수있는 자신의 블로그를 통해 도달 할 수 있습니다 .

특별 감사

이 자습서 시리즈는 많은 유용한 검토자가 검토했습니다. 이 자습서의 수석 검토자는 테레사 머피와 데이비드 수루였습니다. 예정된 MSDN 문서를 검토하는 데 관심이 있으신가요? 그렇다면 선을 놓습니다 mitchell@4GuysFromRolla.com.