강좌와 팁

닷넷 : SqlBulkCopy를 이용한 서버간의 데이터 복사 날짜:2020-4-1 11:04:56 조회수:141
작성자 : 소엔
포인트 : 1388
가입일 : 2020-02-02 00:09:14
방문횟수 : 74
글 187개, 댓글 51개
소개 : SoEn 운영자입니다.
작성글 보기
쪽지 보내기
클래스는 서버간에 대량으로 데이터를 복사할 사용한다. SQL 서버에 포함되어 있는 bcp 벌크 명령과 유사한 동작을 수행한다. 복사를 받는 쪽은 SQL 서버여야 하지만 주는 쪽은 오라클이나 MariaDB 등의 다른 DBMS여도 상관 없다. ADO 통해 데이터를 읽을 수만 있으면 어떤 DBMS에서나 데이터를 가져올 있다.
내부적인 동작 방법은 대단히 복잡하겠지만 사용하는 방법은 간단하다. 절차대로만 코드를 작성하면 된다. 생성자로 이미 열려진 연결 객체를 전달하거나 아니면 연결 문자열을 전달한다. 옵션과 트랜잭션 객체도 전달할 있다.
 
SqlBulkCopy (SqlConnection connection);
SqlBulkCopy (string connectionString, [SqlBulkCopyOptions copyOptions]);
SqlBulkCopy(SqlConnection connection, SqlBulkCopyOptions copyOptions, SqlTransaction externalTransaction);
 
생성자로 전달하는 연결은 출력용이며 연결로 데이터를 보낸다. 주요 속성은 다음과 같다.
 
프로퍼티 타입 설명
DestinationTableName string 목적지의 테이블 이름이다. 디폴트는 null이며 값이 없으면 예외가 발생하므로 반드시 지정해야 한다.
BatchSize int 한번에 복사할 레코드 개수를 지정한다. 디폴트는 0이며 모든 레코드를 일괄 복사한다.
BulkCopyTimeout int 제한 시간을 지정한다. 디폴트는 30초이며 0으로 지정하면 제한 시간을 두지 않는다. 제한 시간 내로 처리하지 않으면 트랜잭션이 롤백된다.
ColumnMappings SqlBulkCopyColumn
MappingCollection
맵핑을 지정한다. 디폴트는 컬렉션이다. 원본과 대상의 테이블 구조가 같다면 맵핑할 필요 없다. 열의 개수나 순서가 다르면 복사할 열을 맵핑한다.
EnableStreaming bool 스트리밍 여부를 지정한다. 디폴트는 false이다. true 변경하면 메모리 사용량이 줄어든다.
     
NotifyAfter int 속성만큼의 레코드를 복사한 알림 이벤트를 생성한다. 디폴트는 0이다.


DestinationTableName  속성은 반드시 지정해야 하며 또한 테이블은 미리 생성되어 있어야 한다. 목적지의 연결과 테이블명을 설정한 다음 메서드로 복사를 수행한다.
 
WriteToServer(IDataReader)        
WriteToServer(DataTable)
WriteToServer(DataRow[])
 
인수는 복사할 원본이다. 리더, 테이블 또는 배열을 전달하면 지정한 서버로 레코드를 복사한다. 대략 복사를 하기 전에 원본 연결을 미리 열어 놓고 테이블을 준비해 두어야 한다. 비동기적으로 복사할 때는 WriteToServerAsync 메서드를 사용한다.
다음 예제는 tblPeople 테이블을 tblPeople2 테이블로 복사한다. 원본 데이터베이스에 tblPeople 테이블이 있어야 하며 목적지에도 tblPeople2 테이블이 존재해야 한다. 서버가 다르다면 테이블 이름은 같아도 상관 없다.
 
using System;
using System.Data.SqlClient;
 
class CSTest {
      static void Main()
      {
             String constr = "Server=(local);database=ADOTest;Integrated Security=true";
            SqlConnection Src = new SqlConnection(constr);
             Src.Open();
             SqlCommand Com = new SqlCommand("SELECT * FROM tblPeople", Src);
             SqlDataReader R = Com.ExecuteReader();
 
             SqlBulkCopy bulkCopy = new SqlBulkCopy(constr);
             bulkCopy.DestinationTableName = "tblPeople2";
             bulkCopy.WriteToServer(R);
 
             R.Close();
             bulkCopy.Close();
      }
}

원본 연결을 열고 모든 레코드를 읽어오는 명령을 실행하여 리더 객체를 생성해 두었다. 리더가 복사할 원본 데이터이며 이후 리더를 통해 원본 테이블의 레코드를 대략으로 읽어 들인다.
같은 서버에 대해 bulkCopy 객체를 생성하고 tblePeople2 테이블을 목적지로 설정한 리더 객체를 인수로 전달하여 WriteToServer 메서드를 호출한다. 내부에서 리더를 통해 읽은 레코드를 목적지 테이블에 하나씩 삽입한다.
예제 실행을 위해 개의 서버를 준비할 없어 편의상 같은 서버에서 복사했는데 이런 용도라면 사실 INSERT SELECT 쿼리문이 훨씬 간편하다. 따라서 SqlBulkCopy 클래스를 같은 서버 내에서 이유는 없으며 주로 서버간의 데이터 복사에 사용한다.
SqlBulkCopyOptions 대량 복사 옵션을 지정한다. 열거형이되 비트 플래그로 정의되어 있어 여러 개의 옵션을 함께 지정할 있다.
옵션 설명
Default 0 아무 옵션도 지정하지 않는다.
KeepIdentity 1 원본 ID값을 유지한다. 지정하지 않으면 목적지의 ID 사용한다.
CheckConstraints 2 복사시 제약을 확인한다.
TableLock 4 복사중에 대량 업데이트 락을 건다. 지정하지 않으면 잠금을 사용한다.
KeepNulls 8 목적 테이블의 NULL값을 유지한다. 지정하지 않으면 NULL 대신 기본값을 사용한다.
FireTriggers 16 삽입하는 행에 대해 트리거를 발생시킨다.
UseInternalTransaction 32 복사 작업을 내부적인 트랜잭션에서 실행한다. 외부 트랜잭션과 함께 사용해서는 안된다.
AllowEncryptedValueModifications 64 암호화된 데이터를 해독하지 않고 복사한다. 양쪽 서버의 암호화 방식이 다르면 복사한 데이터를 없다.
디폴트 옵션은 제약이나 기본값, 트리거 등을 모두 무시하도록 되어 있어 가급적 빠른 속도로 복사하는 것으로 되어 있다. 속도를 희생하더라도 필요한 옵션이 있으면 원하는 옵션을 사용한다.
 



개발자의 천국 SoEn

목록보기 삭제 수정 신고 스크랩


로그인하셔야 댓글을 달 수 있습니다.