다음을 통해 공유


CommandBuilders를 사용하여 명령 생성

SelectCommand 속성이 사용자로부터 텍스트 명령을 받는 쿼리 도구를 통해 런타임에 동적으로 지정되는 경우, 디자인 타임에 적절한 InsertCommand, UpdateCommand, 또는 DeleteCommand를 지정하지 못할 수 있습니다. 단일 데이터베이스 테이블에 DataTable이(가) 맵핑되거나 해당 테이블에서 생성되는 경우, DbCommandBuilder 개체를 이용하여 DeleteCommandInsertCommand, UpdateCommand, DbDataAdapter를 자동으로 생성할 수 있습니다.

자동 명령 생성을 가능하게 하려면 최소 요구 사항으로 SelectCommand 속성을 설정해야 합니다. 속성에 의해 SelectCommand 검색된 테이블 스키마는 자동으로 생성된 INSERT, UPDATE 및 DELETE 문의 구문을 결정합니다.

DbCommandBuilder는 INSERT, UPDATE 및 DELETE SQL 명령을 구성하는 데 필요한 메타데이터를 반환하기 위해 반드시 SelectCommand을 실행해야 합니다. 따라서 데이터 원본에 대한 추가 이동이 필요하며 이로 인해 성능이 저하될 수 있습니다. 최적의 성능을 얻으려면 DbCommandBuilder를 사용하지 말고 명령을 명시적으로 지정하십시오.

또한 SelectCommand는 하나 이상의 기본 키 또는 고유 열을 반환해야 합니다. 없는 경우 예외가 InvalidOperation 생성되고 명령이 생성되지 않습니다.

DataAdapter와 연결될 때, null 참조인 경우 DbCommandBuilder의 속성인 InsertCommand, UpdateCommand, DeleteCommand 속성이 자동으로 생성됩니다. 속성에 Command 대해 이미 있는 경우 기존 Command 속성이 사용됩니다.

둘 이상의 테이블을 함께 조인하여 만든 데이터베이스 뷰는 단일 데이터베이스 테이블로 간주되지 않습니다. 이 경우 명령을 자동으로 생성하는 데 사용할 DbCommandBuilder 수 없습니다. 명령을 명시적으로 지정해야 합니다. DataSet를 데이터 원본에 다시 연결하기 위한 명령을 명시적으로 설정하는 방법에 대한 정보는 DataAdapters를 사용하여 데이터 원본 업데이트를 참조하세요.

출력 매개 변수를 업데이트된 DataSet 행에 다시 매핑하는 것이 좋습니다. 한 가지 일반적인 작업은 데이터 원본에서 자동으로 생성된 ID 필드 또는 타임스탬프를 검색하는 것입니다. DbCommandBuilder 기본적으로 업데이트된 행의 열에 출력 매개 변수를 매핑하지 않습니다. 이 경우 명령을 명시적으로 지정해야 합니다. 자동으로 생성된 ID 필드를 삽입된 행의 열에 다시 매핑하는 예제는 ID 또는 일련 번호 값 검색을 참조하세요.

자동으로 생성된 명령에 대한 규칙

다음 표에서는 자동으로 생성된 명령이 생성되는 방법에 대한 규칙을 보여 줍니다.

명령어 규칙
InsertCommand 데이터 원본에 테이블의 RowStateAdded 조건을 가진 모든 행을 삽입합니다. 업데이트할 수 있는 모든 열에 대한 값을 삽입합니다(ID, 식 또는 타임스탬프와 같은 열은 삽입하지 않음).
UpdateCommand 데이터 원본에서 RowState이(가) Modified인 테이블의 모든 행을 업데이트합니다. ID 또는 식과 같이 업데이트할 수 없는 열을 제외한 모든 열의 값을 업데이트합니다. 데이터 원본의 열 값이 행의 기본 키 열 값과 일치하고 데이터 원본의 나머지 열이 행의 원래 값과 일치하는 모든 행을 업데이트합니다. 자세한 내용은 이 항목의 뒷부분에 있는 "업데이트 및 삭제에 대한 낙관적 동시성 모델"을 참조하세요.
DeleteCommand RowStateDeleted인 테이블의 모든 행에 대해 데이터 원본에서 행을 삭제합니다. 열 값이 행의 기본 키 열 값과 일치하고 데이터 원본의 나머지 열이 행의 원래 값과 일치하는 모든 행을 삭제합니다. 자세한 내용은 이 항목의 뒷부분에 있는 "업데이트 및 삭제에 대한 낙관적 동시성 모델"을 참조하세요.

업데이트 및 삭제에 대한 낙관적 동시성 모델

UPDATE 및 DELETE 문에 대한 명령을 자동으로 생성하는 논리는 낙관적 동시성을 기반으로 합니다. 즉, 레코드는 편집을 위해 잠겨 있지 않으며 다른 사용자 또는 프로세스에서 언제든지 수정할 수 있습니다. 레코드가 SELECT 문에서 반환된 후에 수정될 수 있지만 UPDATE 또는 DELETE 문이 실행되기 전에 자동으로 생성된 UPDATE 또는 DELETE 문에는 WHERE 절이 포함되므로 행이 원래 값을 모두 포함하고 데이터 원본에서 삭제되지 않은 경우에만 업데이트되도록 지정합니다. 이 작업은 새 데이터를 덮어쓰지 않도록 하기 위해 수행됩니다. 자동으로 생성된 업데이트가 삭제되었거나 원래 DataSet에 있는 값이 포함되지 않은 행을 업데이트하려고 시도하는 경우, 명령은 어떤 레코드에도 영향을 주지 않으며 DBConcurrencyException 예외가 발생합니다.

원래 값에 관계없이 UPDATE 또는 DELETE를 완료하려면 자동 명령 생성에 의존하지 않고 해당 값을 명시적으로 설정 UpdateCommandDataAdapter 해야 합니다.

자동 명령 생성 논리의 제한 사항

자동 명령 생성에는 다음과 같은 제한 사항이 적용됩니다.

관련 없는 테이블만

자동 명령 생성 논리는 데이터 원본의 다른 테이블과의 관계를 고려하지 않고 독립 실행형 테이블에 대한 INSERT, UPDATE 또는 DELETE 문을 생성합니다. 따라서 데이터베이스의 외래 키 제약 조건에 참여하는 열에 대한 변경 내용을 제출하도록 호출 Update 할 때 오류가 발생할 수 있습니다. 이 예외를 방지하려면 외래 키 제약 조건과 관련된 열을 업데이트하기 위해 DbCommandBuilder를 사용하지 말고, 대신 작업을 수행하는 데 사용할 문장을 명시적으로 지정하십시오.

테이블 및 열 이름

대괄호로 구분된 경우에도 열 이름 또는 테이블 이름에 공백, 마침표, 따옴표 또는 기타 숫자가 아닌 문자와 같은 특수 문자가 포함된 경우 자동 명령 생성 논리가 실패할 수 있습니다. 공급자에 따라 QuotePrefix 및 QuoteSuffix 매개 변수를 설정하면 생성 논리가 공백을 처리할 수 있지만 특수 문자를 이스케이프할 수는 없습니다. catalog.schema.table 형식의 정규화된 테이블 이름이 지원됩니다.

CommandBuilder를 사용하여 SQL 문 자동 생성

그런 다음 DataAdapterSelectCommand 속성을 먼저 설정하고, DataAdapter 객체를 생성한 후, CommandBuilder가 자동으로 SQL 문을 생성할 수 있도록 DataAdapter를 인수로 지정해야 합니다.

' Assumes that connection is a valid SqlConnection object
' inside of a Using block.  
Dim adapter As SqlDataAdapter = New SqlDataAdapter( _  
  "SELECT * FROM dbo.Customers", connection)  
Dim builder As SqlCommandBuilder = New SqlCommandBuilder(adapter)  
builder.QuotePrefix = "["  
builder.QuoteSuffix = "]"  
// Assumes that connection is a valid SqlConnection object  
// inside of a using block.  
SqlDataAdapter adapter = new SqlDataAdapter(  
  "SELECT * FROM dbo.Customers", connection);  
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);  
builder.QuotePrefix = "[";  
builder.QuoteSuffix = "]";  

SelectCommand 수정하기

INSERT, UPDATE 또는 DELETE 명령이 자동으로 생성된 후에 CommandTextSelectCommand을 수정하면 예외가 발생할 수 있습니다. 수정된 SelectCommand.CommandText 내용에 삽입, 업데이트 또는 삭제 명령이 자동으로 생성될 때 사용된 것과 일치하지 않는 SelectCommand.CommandText 스키마 정보가 포함된 경우 메서드에 대한 DataAdapter.Update 향후 호출은 현재 테이블에서 참조하는 열에 더 이상 존재하지 않는 열에 SelectCommand액세스하려고 시도할 수 있으며 예외가 throw됩니다.

CommandBuilderRefreshSchema 메서드를 호출하여 CommandBuilder에 의해 명령을 자동으로 생성하는 데 사용되는 스키마 정보를 새로 고칠 수 있습니다.

자동으로 생성된 명령을 확인하려면 GetInsertCommand 개체의 GetUpdateCommand, GetDeleteCommand, CommandBuilder 메서드를 사용하고 연결된 명령의 CommandText 속성을 검사하여 자동 생성된 명령에 대한 참조를 얻을 수 있습니다.

다음 코드 예제에서는 자동으로 생성 된 업데이트 명령을 콘솔에 씁니다.

Console.WriteLine(builder.GetUpdateCommand().CommandText)  
Console.WriteLine(builder.GetUpdateCommand().CommandText);

다음 예제는 Customers 데이터 세트의 custDS 테이블을 다시 만듭니다. RefreshSchema 메서드는 이 새 열 정보를 사용하여 자동으로 생성된 명령을 새로 고치기 위해 호출됩니다.

' Assumes an open SqlConnection and SqlDataAdapter inside of a Using block.  
adapter.SelectCommand.CommandText = _  
  "SELECT CustomerID, ContactName FROM dbo.Customers"  
builder.RefreshSchema()  
  
custDS.Tables.Remove(custDS.Tables("Customers"))  
adapter.Fill(custDS, "Customers")  
// Assumes an open SqlConnection and SqlDataAdapter inside of a using block.  
adapter.SelectCommand.CommandText =
  "SELECT CustomerID, ContactName FROM dbo.Customers";  
builder.RefreshSchema();  
  
custDS.Tables.Remove(custDS.Tables["Customers"]);  
adapter.Fill(custDS, "Customers");  

참고하십시오