SimpleIsBest.NET

유경상의 닷넷 블로그

닷넷의 발견: Batch Update Using DataAdapter

by 블로그쥔장 | 작성일자: 7/9/2008 7:25:00 PM
이 글은 오래된 전에 작성된 글입니다. 따라서 최신 버전의 기술에 알맞지 않거나 오류를 유발할 수 있습니다. 저자는 이 글에 대한 질문을 받지 않을 것입니다. 하지만 이 글이 리뉴얼 되면 이 글에 대한 질문을 하거나 토론을 할 수도 있습니다.

요즘엔 글을 자주(?) 올리네요. 이 글은 2006년 초에 쓰려고 마음먹었던 내용이지만 이제서야 실제로 글을 쓰게 된 그 유명한 "DataAdapter를 이용한 배치 업데이트" 입니다. 장장 28개월을 미루어 재낀 저의 게으름에도 거의 절로 감탄사가 나옵니다(접시물에 코박고 뒤져야 할듯...). 슈퍼맨이나 스파이더맨, 하다 못해 그 싸가지 없다는 핸콕도 가지고 있는 초능력을 제가 가지고 있는 것도 아니고, 레어 아이템이나 현질 아이템 같은 아이템 빨로 버티는 배트맨처럼 셋템을 맞춘 것도 아니고, 가진 거라곤 무지하게 허접한 쑛 하나와 2연장 Fire ball 뿐인 필자가 뭐가 있겠습니까? 그냥 조낸 아는 척만 하는 거지요. 쩌업......

닷넷의 발견: Batch Update Using DataAdapter

닷넷의 발견

그렇다. 닷넷 프레임워크 2.0이 우리에게 다가 온지도 졸라 오랜 시간이 흘렀다. IT 세계에서 2년이라면 조낸 긴 시간 아닌가? 닷넷 프레임워크 3.0이 나온 지도 오래되었으며 닷넷 프레임워크 3.5가 꼬리를 친 지도 벌써 몇 개월이나 흘렀다. 그럼에도 불구하고 우린 아직도 닷넷 프레임워크 2.0에 새로이 추가된 기능들을 모두 숙지하고 활용하고 있는가? 이 질문에 쉽게 "그렇다"라고 대답할 수 있는 인간이라면 바로 gg 치고 엎드려 존경을 외쳐야만 할 것이다.

필자를 비롯하여 많은 개발자, 아니 대다수의 개발자는 입에 풀칠하는데 바쁜 관계로 닷넷 프레임워크의 많은 기능들을 충분히 활용하지 못하고 있음은 두말하면 잔소리가 되겠다. 그렇다고 코 빠뜨리고 주저 앉아만 있을 수는 없는 일! 초급에서 중급으로 다시 중급에서 고급으로 올라서야 하며 궁극적으로 개발자들이 제대로 대접받는 그때까지 우린 우리의 가치를 올리는데 노력해야 할 것이다. 쓰~바~

헛소리는 그만하고 본론으로 들어가 보자. 이번 포스트에서는 ADO.NET의 DataAdapter 객체를 이용하여 데이터베이스를 업데이트하는 방법을 살펴보고자 한다. 과거 호랭이 담배 피던 시절부터 ADO.NET을 통해 데이터베이스를 업데이트 하는 방법 중 하나로 DataSet과 DataAdapter를 조합하여 다수의 데이터를 갱신하는 방법이 전해져 내려오고 있었다. 뭐 닷넷 개발자라면 DataAdapter 클래스의 Update 메쏘드를 이용하면 DataSet 내에서 추가/수정/삭제된 데이터가 데이터베이스 내에 반영된다는 사실을 알고 있을 것이다.

DataAdapter를 이용한 데이터베이스 갱신 작업은 그다지 널리 사용되지 않고 있는데 그 이유는 반드시 DataSet을 사용해야 한다는 점과 데이터베이스 업데이트 과정을 개발자가 세세히 제어하기 쉽지 않다는 점 그리고 그런 기능이 있는 줄 몰라서 이다. 필자를 비롯한 독자들 역시 DataAdapter의 Update 메쏘드 대신 직접 INSERT, UPDATE, DELETE 쿼리를 작성하고 이 쿼리에 대해 ExecuteNonQuery를 불러 조지는 형태의 데이터베이스 갱신 작업에 많이 익숙해져 있을 것이다.

오랜 설움을 받아오던 DataAdapter.Update 메쏘드가 닷넷 프레임워크 2.0에 와서 장족의 발전을 하였으니 고거이 바로 배치 업데이트가 되겠다. DataAdapter를 이용한 배치 업데이트란 DataSet 내의 여러 레코드에 대한 INSERT/UPDATE/DELETE 쿼리를 한 방에 데이터베이스에 날릴 수 있는 기능을 말한다. 무슨 말인지 잘 이해가 안 간다면 일단 숏을 잡고 5초간 묵념을 한 후에 즐거이 이 글을 읽어 주면 되겠다.

Data Update using DataAdapter 

DataAdapter를 이용하여 데이터베이스를 변경하기 위해서는 이 클래스의 Update 메쏘드를 호출해야 한다. Update 메쏘드는 DataSet이 제공하는 변경 추적 기능을 이용하여 DataSet 내에 변경된 DataRow 들에 대해 DataAdapter 클래스의 InsertCommand, UpdateCommand, DeleteCommand 가 호출되어 데이터베이스에 대한 변경을 수행한다.

DataTable의 데이터 변경 추적에 관련된 기능은 DataRow의 RowState 속성 및 DataRowVersion 에 의해 제공된다. 상세한 내용은 MSDN의 다음 자료들을 참고하기 바란다. 심심해서 달아준 링크가 아니다. 읽어 보면 다 도움이 된다. 가끔은 MSDN의 허접한 번역에 놀라며 영문 자료를 찾는 자신을 발견할 수도 있지만 말이다...... (잉글리쉬 커뮤니케이션에 핸디캡이 적은 사람이라면 사람은 영문 자료를 읽기를 권한다...)

DataAdapter를 이용하여 DataSet 혹은 DataTable를 변경하는 구체적인 방법에 대해서는 다음 MSDN 자료를 참고하자.

DataAdapter를 이용하여 데이터 소스(대개 데이터베이스이다)를 업데이트하는 방법은 제공한 MSDN 자료에서 잘 설명되었듯이 DataAdapter의 Update 메쏘드를 호출하여 변경된 데이터들에 대해서는 UpdateCommand 를, 추가된 데이터에 대해서는 InsertCommand를, 그리고 삭제된 데이터에 대해서는 DeleteCommand를 반복적으로 수행하는 것을 말한다.

DataAdapter의 Update 메쏘드를 이용한 데이터 변경은 필자를 비롯한 개발자들 사이에서 선호하는 방법이 아니었다. 그 이유는 DataAdapter의 Update 메쏘드를 사용하기 위해서는 반드시 DataTable 이 필요했기 때문이다. 수정할 데이터가 항상 DataTable 을 통해 전달되지 않을 수도 있으며 한 건의 데이터 레코드를 추가/수정/삭제하기 위해 DataTable과 DataAdapter를 구성한다는 것 자체가 부담이 크기 때문이다.

또 한가지 DataAdapter의 Update 메쏘드를 기피하는 이유는 다량의 데이터 변경이 개발자의 제어 바깥에서 이루어 진다는 점이다. 즉, 반복적으로 데이터를 추가/수정/삭제 함에 있어서 개발자는 단순히 Update 메쏘드를 호출하는 것이 전부이기 때문이다. 단일 Update 메쏘드 호출 내에서 다수의 레코드가 추가/수정/삭제 된다는 것은 어찌 보면 편리하지만 개발자는 이처럼 자신의 제어하지 않는 코드에 의해 어떤 작업이 수행되는 것을 그다지 선호하지 않는 경향이 많다. 실제로는 DataAdapter 가 제공하는 RowUpdating 이벤트와  RowUpdated 이벤트, 그리고 ContinueUpdateOnError 속성에 의해 개발자는 데이터 업데이트 과정을 충분히 제어할 수 있음에도 불구하고 말이다. (필자를 비롯한 많은 개발자가 자신의 눈에 보이지 않는 코드를 잘 믿지 않는다. ㅎㅎ)

마지막으로 DataAdapter를 이용한 데이터 갱신이 많이 사용되지 않는 이유는 "익숙하지 않기 때문"이다. 과거에는 이러한 기능이 제공되지 않았기 때문에 추가/수정/삭제하는 쿼리를 직접 생성하고 이것을 "수행"하는 것이 일반적인 데이터 갱신 방법이었다. 단순히 이러한 데이터 베이스 갱신에 익숙하기 때문에 그냥 그렇게 사용하는 것도 DataAdapter의 Update가 널리 사용되지 않는 간과할 수 없는 이유 중 하나이다.

Batch Updating using DataAdapter

DataAdapter의 Update 메쏘드를 호출하면 DataTable 내의 변경된 DataRow 들에 대해 UpdateCommand, InsertCommand, DeleteCommand 가 수행된다고 했다. Update 메쏘드의 기본 행동 방식은 변경된 각 DataRow 에 대해 반복적으로 데이터베이스를 호출한다. 즉, DataTable 내에 20개의 추가/수정/삭제된 DataRow가 존재하면 20번의 DB 호출이 발생한다는 것이며 이는 데이터베이스와 20회의 라운드 트립(round-trip)이 발생한다는 것과 같다.

아는 독자들은 알겠지만 클라이언트와 서버 사이의 라운드 트립이 많으면 많을 수록(chatty 호출이라 한다) 성능적인 불리함을 안게 된다. 네트워크는 CPU 보다 말도 못하게 느리며 메모리와도 쨉이 안될 정도로 느릴 뿐만 아니라 디스크보다도 매우 느리다. 따라서 네트워크 액세스를 적게 하면 할 수록 성능적으로 유리하다는 말이다. 이런 관점에서 DataAdapter의 Update 메쏘드는 사용은 편리하지만 성능적으로는 그저 그런 기능이 되고 만다.

닷넷 프레임워크 2.0은 데이터 소스(데이터 베이스)와의 라운드 트립을 감소시키기 위해 DataAdapter의 UpdateBatchSize 속성을 제공한다. UpdateBatchSize 속성은 DataAdpater의 Update 메쏘드가 호출될 때 데이터 소스에 제출할 추가/수정/삭제 커맨드의 개수를 나타낸다. UpdateBatchSize 속성의 디폴트 값은 1 으로써 이전 버전의 닷넷 프레임워크와 동일하게 매 DataRow에 대해 하나의 커맨드 만을 수행하게 된다. UpdateBatchSize 속성을 1이 아닌 양의 정수 값으로 설정하면 주어진 값만큼의 커맨드가 한번에 데이터 소스에 제출된다. 예를 들어 DataTable에 20개의 변경된 DataRow가 존재하고 UpdateBatchSize 속성의 값을 10으로 설정한 후, 이 DataTable에 대해 DataAdapter.Update 메쏘드를 호출하면 10의 추가/수정/삭제 커맨드가 포함된 데이터 소스 호출이 2회 발생한다는 말이다. 이전 버전의 닷넷 프레임워크를 사용하거나 UpdateBatchSize 의 기본 값인 1을 사용했다면 데이터 소스와 20회의 라운드 트립이 발생하지만 UpdateBatchSize 의 값을 10으로 설정함으로써 겨우 2회의 라운드 트립 만이 발생하기 때문에 성능 향상을 기대할 수 있을 것이다. 그리고 추가/수정/삭제할 DataRow의 개수가 클 수록 성능 향상의 폭도 커진다.

DataAdapter를 통한 배치 업데이트를 지원하는 DataAdapter 객체는 System.Data.SqlClient, System.Data.OracleClient 네임스페이스, 그리고 ODP.NET의 Oracle.DataAccess.Client 네임스페이스의 DataAdapter 객체이다. System.Data.OleDb, System.Data.Odbc 네임스페이스의 DataAdapter 객체는 UpdateBatchSize 속성을 액세스하면 NotSupportedException 예외가 발생한다.

이쯤 되면 예제 코드가 등장해 줘야 할 것 같다. [리스트1]은 전형적인 DataAdapter를 이용한 데이터 베이스 갱신 코드의 예제를 보여준다.

private int UpdateBatch(DataTable dt)

{

    string insertQuery = "INSERT INTO BatchUpdateTest(PK, COL1, COL2) VALUES(@pk, @col1, @col2)";

    string updateQuery = "UPDATE BatchUpdateTest SET PK = @pk, COL1 = @col1, COL2 = @col2 WHERE PK = @org_pk";

    string deleteQuery = "DELETE FROM BatchUpdateTest WHERE PK = @org_pk";

    SqlConnection conn = new SqlConnection("SERVER=(local);Trusted_Connection=true");

    SqlCommand insertCommand = new SqlCommand(insertQuery, conn);

    SqlCommand updateCommand = new SqlCommand(updateQuery, conn);

    SqlCommand deleteCommand = new SqlCommand(deleteQuery, conn);

    SqlDataAdapter adapter = new SqlDataAdapter();

 

    // Insert 커맨드 설정

    insertCommand.Parameters.Add("@pk", SqlDbType.Int, 4, "PK");

    insertCommand.Parameters.Add("@col1", SqlDbType.NVarChar, 32, "COL1");

    insertCommand.Parameters.Add("@col2", SqlDbType.Int, 4, "COL2");

    insertCommand.UpdatedRowSource = UpdateRowSource.None;

    adapter.InsertCommand = insertCommand;

    // Update 커맨드 설정

    updateCommand.Parameters.Add("@org_pk", SqlDbType.Int, 4, "PK").SourceVersion = DataRowVersion.Original;

    updateCommand.Parameters.Add("@pk", SqlDbType.Int, 4, "PK");

    updateCommand.Parameters.Add("@col1", SqlDbType.NVarChar, 32, "COL1");

    updateCommand.Parameters.Add("@col2", SqlDbType.Int, 4, "COL2");

    updateCommand.UpdatedRowSource = UpdateRowSource.None;

    adapter.UpdateCommand = updateCommand;

    // Delete 커맨드 설정

    deleteCommand.Parameters.Add("@org_pk", SqlDbType.Int, 4, "PK").SourceVersion = DataRowVersion.Original;

    deleteCommand.UpdatedRowSource = UpdateRowSource.None;

    adapter.DeleteCommand = deleteCommand;

 

    // DataAdapter 설정

    adapter.ContinueUpdateOnError = true;

    adapter.UpdateBatchSize = 0;             // Batch Update 수행 !

 

    int records = -1;

    conn.Open();

    try {

        records = adapter.Update(dt);

    }

    finally {

        conn.Close();

    }

    return records;

}

리스트1. DataAdapter를 이용한 Batch Update 예제 코드

DataAdapter를 이용하여 DataTable의 변화사항을 데이터베이스에 업데이트하기 위해서는 추가/수정/삭제에 대해 각각 커맨드 객체를 생성하고 이를 DataAdapter의 InsertCommand, UpdateCommand, DeleteCommand 속성에 설정해 주어야 한다. 이들 추가/수정/삭제 커맨드를 구성할 때는 일반적인 방법과 같이 INSERT, UPDATE, DELETE 쿼리 문장을 구사하거나 저장 프로시저를 호출해도 된다. 다만 커맨드의 매개변수를 구성할 때에는 기존 ExecuteNonQuery를 호출했을 때와 다른 접근을 해야 한다.

DataAdapter의 Update 메쏘드가 호출되면 DataTable에서 변경된 DataRow 들에 대해 추가/수정/삭제 커맨드들이 반복적으로 호출되기 때문에 커맨드 객체의 매개변수 객체(이 경우 SqlParameter 객체)를 구성할 때 매개변수의 구체적인 값을 지정할 수 없다. 친절한 ADO.NET 씨는 매개변수 객체가 값으로 사용할 DataRow의 컬럼 이름을 지정하면 커맨드가 수행될 때 해당 컬럼의 값을 매개변수 값으로 사용한다.

이외에도 DataTable의 삭제, 변경 내용을 데이터베이스에 적용할 때 컬럼의 값을 Original 값을 사용할 것인가 아니면 Current 값을 사용할 것인가에 대해서도 주의해야 하는데, 이 내용은 배치 업데이트에만 적용되는 사항이 아니므로 더 이상 상세히 언급하지 않겠다. MSDN의 "행 상태 및 행 버전"에 대한 문서를 참고하기 바란다.

[리스트1]에서도 매개변수 객체를 커맨드 객체에 추가할 때 구체적인 매개변수 값 대신 컬럼 이름을 지정하고 있다. 다음 코드에서 세 개의 매개변수 @pk, @col1, @col2 의 값은 DataRow에서 PK, COL1, COL2 라는 컬럼의 값을 구체적인 매개변수 값으로 사용하게 된다.

    insertCommand.Parameters.Add("@pk", SqlDbType.Int, 4, "PK");

    insertCommand.Parameters.Add("@COL1", SqlDbType.NVarChar, 32, "COL1");

    insertCommand.Parameters.Add("@COL2", SqlDbType.Int, 4, "COL2");

배치 업데이트를 수행하고자 한다면 DataAdapter의 UpdateBatchSize 속성의 값을 1이 아닌 값으로 주어야만 한다. 이 값을 1로 설정하면 배치 업데이트는 수행되지 않는다. [리스트 1]에서는 UpdateBatchSize 속성의 값을 0으로 설정하였는데 이 속성에 0 이 지정되면 데이터 프로바이더(이 경우 SQL Server 프로바이더)에게 적절한 배치 크기를 설정하도록 위임하게 된다.

배치 업데이트를 수행하기 위해 추가적으로 설정해야 할 작업은 추가/수정/삭제 커맨드의 UpdateRowSource 속성의 값을 None 혹은 OutputParameters 로 설정해야 한다는 것이다. UpdateRowSource 속성은 추가/수정/삭제의 업데이트 결과를 어떻게 받아올 것인가를 지정하는 속성으로써 UpdateRowSource 열거 타입인 None, OutputParameter, FirstReturnedRecord, Both 중 하나의 값으로 설정할 수 있으며 디폴트는 Both 이다. 하지만 배치 업데이트는 한 번에 여러 업데이트 커맨드를 데이터베이스에 제출하므로 중간에 결과셋을 받아 올 수 없다. 따라서 배치 업데이트에서는 None 이나 OutputParameter 값 만이 UpdateRowSource 속성에 유효한 값이 된다. [리스트 1]에서도 각 커맨드의 UpdateRowSource 속성의 값을 None으로 설정하고 있음을 알 수 있을 것이다.

    // Insert 커맨드 설정

    ......   

    insertCommand.UpdatedRowSource = UpdateRowSource.None;

    adapter.InsertCommand = insertCommand;

 

    // Update 커맨드 설정

    ...... 

    updateCommand.UpdatedRowSource = UpdateRowSource.None;

    adapter.UpdateCommand = updateCommand;

 

    // Delete 커맨드 설정

    ......

    deleteCommand.UpdatedRowSource = UpdateRowSource.None;

    adpater.DeleteCommand = deleteCommand; 

마지막으로 언급할 부분은 DataAdapter 객체의 ContinueUpdateOnError 속성에 대한 내용이다. 이 속성은 업데이트 도중 오류가 발생하면 예외를 발생할 것인지를 결정한다. 기본 값은 false 이며, 업데이트 도중 오류가 발생하면 즉시 예외가 발생하고 업데이트는 중단된다. 이 속성을 true로 설정하면 업데이트 도중 오류가 발생하더라도 다음 DataRow에 대해 계속적으로 업데이트 작업을 수행한다. 발생한 오류 정보는 DataRow 객체의 RowError 속성에 기록된다. 이 속성은 배치 업데이트를 사용하건 사용하지 않건

Consideration in Batch Update

배치 업데이트가 무엇이고 어떤 장점이 있는가 살펴보았으니 이제 배치 업데이트를 실제로 사용하고자 할 때 고려 사항이나 주의 사항에 대해 몇 가지 살펴보도록 하자.

배치 업데이트를 사용할 때 첫째로 주의할 부분은 "배치"라는 용어의 함정에 빠지지 말아야 한다는 것이다. 배치 업데이트를 수행하면 여러 커맨드가 한번에 데이터베이스에 제출되어 데이터베이스와의 라운드 트립이 감소할 뿐이며 실제 업데이트는 배치 업데이트를 사용하지 않았을 때와 동일한 문맥 하에서 수행된다. SQL Server의 경우 명시적으로 트랜잭션을 시작하지 않으면 자동으로 트랜잭션이 배치 단위로 잡힌다. 하지만 DataAdapter가 수행하는 배치 업데이트는 SQL Server의 배치가 아니며 각각의 업데이트 커맨드가 하나의 SQL Server 배치로써 수행된다. 따라서 업데이트 도중 오류가 발생하면 오류 발생 이전에 수행된 업데이트는 적용이 된다.

구체적인 예를 들어, UpdateRowSize 속성을 10으로 설정하여 배치 크기를 10으로 잡았고 10개의 업데이트 커맨드를 수행하다가 6번째에서 오류가 발생했다고 가정해 보자. SQL Server의 경우 트랜잭션을 명시적으로 사용하지 않았다면 이미 수행된 5개의 커맨드는 커밋이 되어 데이터베이스에 적용이 되어 버리게 된다는 것이다. 이는 10개의 커맨드를 담는 DataAdapter 배치 업데이트가 SQL Server에서 말하는 "배치"와 다른 의미임을 확실하게 보여준다.

반면 오라클은 SQL Server와 다르게 자동 트랜잭션이 활성화 되어 있지 않다. 이 때문에 DataAdapter를 통해 배치 업데이트를 수행하면 DataAdapter의 배치는 오라클의 배치와 동일하게 적용된다. 쉽게 말해 10개의 업데이트 커맨드 중 어느 하나라도 오류를 유발하면 전체 10개의 업데이트는 롤백 된다는 얘기이다.

이처럼 DataAdapter의 "배치" 업데이트는 어떤 데이터베이스, 그리고 그 데이터베이스의 설정에 따라서 다르게 작용할 수 있다. 따라서 미리 테스트를 수행 해보고 배치 업데이트의 결과에 대한 정확한 판단을 해야만 한다. 한가지 확실한 것은 배치 업데이트를 통해 데이터베이스와의 라운드 트립을 줄일 수 있다는 것이다.

배치 업데이트에서 두 번째 주의할 사항은 UpdateBatchSize 속성의 값을 너무 크게 주면 오히려 성능이 나빠질 수 있다는 것이다. 하지만 어떤 값이 적당한가를 알아내기란 쉽지 않다는 것이 문제이다. 대안으로 UpdateBatchSize 속성을 0으로 지정하여 데이터 프로바이더가 알아서 하도록 쌩깔 수도 있지만 웬지 응가하고 밑 안 닦은 기분이 드는 것은 사실이다. 따라서 배치 업데이트를 하기 전에 대량의 데이터를 추가/수정/삭제하는 테스트를 수행하여 성능을 해치지 않는 UpdateBatchSize를 알아내는 것이 좋을 것이다.

마지막 주의 사항은 배치 업데이트 뿐만 아니라 DataAdapter의 Update 메쏘드를 호출할 때의 일반적인 주의 사항이 되겠다. Update 메쏘드는 업데이트를 수행할 때 DataTable에서 변경된 DataRow의 순서대로 추가/수정/삭제를 수행한다. 이러한 행동은 많은 데이터를 업데이트할 때 오류를 유발할 수 있다. 예를 들어 한 레코드를 삭제하고 삭제된 DataRow와 동일한 키를 갖는 새로운 레코드를 추가했다고 가정해 보자. 만약 DataTable의 순서 상 추가된 DataRow가 삭제된 DataRow 보다 앞서 존재한다면 DataRow를 추가하는 InsertCommand는 Primary Key 제약 조건을 위반하게 된다. 비슷하게 어떤 레코드를 키를 수정(Update)하고 키가 수정된 레코드의 원래 키 값으로 새로운 레코드가 추가될 때도 DataRow의 순서에 따라 업데이트가 성공할 수도 실패할 수도 있다. 단순히 DataAdapter의 Update를 호출해서는 이러한 오류를 피할 수 없다.

이러한 문제의 일반적인 해결책은 삭제, 수정, 추가의 순서대로 일괄 작업을 수행하는 것이다. DataTable에는 GetChanges 메쏘드가 존재하고 이 메쏘드를 통해 삭제된 레코드들, 수정된 레코드들, 추가된 레코드들을 추출하는 것이 가능하므로 이들에 대해 각각 Update 메쏘드를 호출해 주어야 한다. 상세한 예제는 "패스~~~".

Epilog

덴장... 이번 포스트도 시간을 너무 많이 소비해 버렸다. 날로 쳐먹으려고 고른 토픽인데 계획보다 이틀이나 더 작업했으며 생각 보다 많은 시간을 테스트와 글을 쓰는데 소요했다. 세상엔 쉬운 게 하나도 없어 보인다. 요즘 같이 할 일은 많고 시간에 쫓길 때는 더욱더 그런 것 같다. 짧은 시간 동안만 글을 쓰더라도  많은 독자들이 좋아할 만한 그런 토픽은 없을까? 쓸데없이 아는 척을 많이 해서 이렇게 시간이 많이 걸리는 것일까? (실은 내용 중 틀린 것이 있으면 쪽 팔리니깐 이거 저거 많은 테스트를 해서 그런 것 같다...)

아놔...... 오늘 따라 SG 워너비의 Timeless 란 노래가 졸라 생각난다. 우~~~~~워~~~~~



Comments (read-only)
#re: 닷넷의 발견: Batch Update Using DataAdapter / 엔틱스 / 7/9/2008 11:17:00 PM
역쉬 계획하신대로 착착 포스트를 작성하시는군요~!!!
저도 시간을 쪼개어서 제 블로그에 글을 올려야 할 텐데요... ㅠㅠ
블로그에 포스팅할 소스좀 주세요~!!! ^^;;

ps. 언제나 다시 한번 감탄을 느끼게 하는 글. 감사합니답~!!!
#re: 닷넷의 발견: Batch Update Using DataAdapter / 블로그쥔장 / 7/9/2008 11:20:00 PM
엔틱스님... 저도 토픽에 밑천이 떨어져가는지라...
뭐 엔틱스님 블로그 가보니깐 여러가지 토픽 많이도 있던뎅...
ASP.NET도 토픽 거리는 무진장 있답니다.
다만 시간이 없을 뿐이지... ㅎㅎ
#re: 닷넷의 발견: Batch Update Using DataAdapter / 웹지니 / 7/10/2008 8:41:00 AM
쥔장님! 오랜만에 좋은 글 잘 읽고 갑니다.
위의 답글 마지막 멘트에 심히 공감이 가네요. "다만 시간이 없을 뿐..." ㅠㅠ
#re: 닷넷의 발견: Batch Update Using DataAdapter / 탱옹 / 7/11/2008 3:19:00 PM
호오.. 이렇게 시간이 없는 와중에도 포스트를 했단 말씀입니까?
진짜 대단한 끈기력이 아닐 수 없습니다. 박수를 보냅니다.
#re: 닷넷의 발견: Batch Update Using DataAdapter / r김완섭 / 7/24/2008 11:59:00 PM
글 잘 읽었습니다.
시간이 없는 관계로 따라해보기도 시간이 없을뿐 훗~~
.NET은 넘 기능이 많아서 두렵기까지 하네요.
#re: 닷넷의 발견: Batch Update Using DataAdapter / 가이아 / 7/31/2008 9:13:00 AM
음... 글 잘 읽었습니다. 단순 IUD에는 사용하겠는데.. 추가적인 복잡한 비지니스룰이 추가되면 역시나 사용하기 힘들듯 싶으네요...
XML Bulk 방식이 좀더 범용적인 응용에서는 선호될듯한... 나름 생각~
#re: 닷넷의 발견: Batch Update Using DataAdapter / 이경원 / 8/5/2008 9:15:00 AM
잘 보고 갑니다..^^
#아이제 처음부터 현재 읽는 것을 마치게됬네요,,,,오늘 하루가 다갔습니다. / Cryptomin / 9/8/2008 5:08:00 PM
매우매우 감사합니다.
저도 실력이 된다면 .......
많은 도움 받았습니다.....

출근해서 처음부터 끝까지...다보았습니다....이제 퇴근 시간이 되었네요,,,

^ ^
#re: 닷넷의 발견: Batch Update Using DataAdapter / 마크툽 / 12/9/2008 11:14:00 PM
좋은 글 잘 읽었습니다.
역시...나 글에서 조차도 고수의 초식이 느껴집니다.
이것저것 따라하면서 한가지 이상한 점(?) 을 발견했는데요. 여기저기 뒤져봐도 명확한 답을 구해지 못했습니다.
글에서 처럼
10으로 설정하여 배치 크기를 10으로 잡았고 10개의 업데이트 커맨드를 수행하다가 6번째에서 오류가 발생했다라면
명시적으로 트랜젝션을 사용하지 않았을 경우 5개는 커밋 되고 6번째 는 에러 발생후 그리고 7,8,9,10 번째는 skip 할 것으로 예상 했었는데요
( ContinueUpdateOnError 속성을 false 로 설정 해논 상태구요.)
그런데 7,8,9,10 까지 업데이트 커멘드를 실행 하더라는 것입니다.
해서 나름 RowUpdating 이벤트와 RowUpdated 이벤트를 사용하여 7,8,9,10 행을 스킵하도록 해보려 했으나...
RowUpdated 이벤트는 모든 커맨드가 배치작업으로 끝이 난 후에 발생 하고, RowUpdating은 업데이트 커맨드 실행전에 발생하여
이를 통해서는 처리를 할 수 없었어요.
물론 7,8,9,10행을 실행하는것이 크게 문제되지 않을 것으로 판단 하였는데..

System.Transaction 으로 배치작업을 트랜젝션으로 묶었을 경우 이미 6행째에서 에러 발행 후 트랜젝션 롤백이 일어남으로
7,8,9,10행은 업데이트 커맨드를 수행할 의미가 없을 텐데요..

음.. 나름 배치 작업에서는 10행을 모두 처리 후 트랜젝션을 처리한다 라고 정리는 해보았지만..

진정 10개의 업데이트 커멘드 중 6행에서 에러 발생시 배치 작업을 중단하고 빠져 나올 방법이 없는것인지...

고수님의 한 초식 부탁 드립니다. ^^;

어쩌면 위 내용에 대해 이글을 읽으신 분들에게 한가지 더 팁을 주신다는 생각으로 .. ^^


#re: 닷넷의 발견: Batch Update Using DataAdapter / naggingmachine / 12/31/2008 1:04:00 PM
좋은 글 잘 읽었습니다. 어찌 그리 글을 이해하기 쉽게 쓰시는지요~~~
#re: 닷넷의 발견: Batch Update Using DataAdapter / 브래드류 / 4/2/2009 11:20:00 AM
꼬박꼬박 읽을뿐... 실무엔 적용할 생각도 못해보는 두려움...
#re: 닷넷의 발견: Batch Update Using DataAdapter / 김뱅 / 5/29/2009 11:46:00 AM
수고 많으십니다. 엇그제 WCF 세미나에서 얼굴 뵜습니다. ㅎㅎ
힘내세요.
#re: 닷넷의 발견: Batch Update Using DataAdapter / 나무꾼 / 8/10/2009 5:49:00 PM
좋은 글 잘 읽고 갑니다. 문장 한 줄 한 줄에 정성이 느껴지는 포스트입니다.
종종 방문하겠습니다.