커맨드 수행¶
Fox DB Access 를 통해 데이터베이스에서 SQL 문장을 수행하거 저장 프로시저를 호출하기 위해서는 Execute- 시리즈의 메서드를 호출해야 합니다. Execute- 시리즈 메서드들은 내부적으로 Command 객체를 만들고 필요한 설정과 매개변수 지정을 하고 SQL 문장 혹은 저장 프로시저를 수행하고 그 결과를 반환합니다.
FoxDbAccess 클래스 및 그 파생 클래스들은 수행하고자 하는 데이터베이스 작업과 그 결과값에 따라 매우 다양한 Execute- 시리즈 메서드를 제공합니다. 매우 많은 메서드들을 빠르게 이해하는 방법으로 메서드 이름에 사용된 2 종류의 접미사를 이해하면 도움이 됩니다.
이 문서와 관련된 예제 코드는 다음 예제를 참조 하십시요.
- Fox Db Access Overview 예제 의 executing_command 프로젝트
Execute- 메서드 접미사¶
예를 들어 ExecuteSpDataSet 메서드는 Sp 접미사와 DataSet 접미사를 쓰는 Execute- 메서드입니다. Sp 접미사는 저장 프로시저를 수행한다는 의미의 접미사이며 DataSet 접미사는 수행결과를 DataSet 객체로 반환함을 나타내는 접미사 입니다.
수행 대상 접미사 ¶
첫번째 접미사는 Execute- 시리즈 메서드가 수행할 데이터베이스 작업을 나타냅니다.
-
-Sql-: SQL 문장을 수행합니다. 전통적인 코딩 방식으로 이야기 하자면CommandType.Text에 해당하는 작업을 수행합니다. 이들 메서드들은 수행할 SQL 문장을 첫번째 매개변수로 사용합니다. -
-Sp-: 저장 프로시저를 수행합니다. 전통적인 코딩 방식으로는CommandType.StoredProcedure에 해당하는 작업을 수행합니다. 이들 메서들은 수행할 저장 프로시저 이름을 첫번째 매개변수로 사용합니다.Note
사용하는 Npgsql 버전에 따라
ExecuteSp-메서드가 호출하는 대상이 달라집니다. Npgsql 7.x 버전부터는ExecuteSp-가 저장 프로시저를 호출하지만 그 이전 버전은 함수를 호출합니다. PostgreSQL 을 사용할 때 저장 프로시저보다 함수를 주로 사용한다면 다음 호출을 통해 Npgsql 7.x 이상 버전에서도ExecuteSp-메서드가 함수를 호출하도록 지정할 수 있습니다. -
-Query-: Fox Query 를 수행합니다. Fox Query 는.foxml파일에서 SQL 문장, 데이터베이스 매개변수 정보를 포함하고 있습니다.ExecuteQuery-메서드는 이러한 정보를 읽어Command객체를 구성하고 수행하며 그 결과를 반환합니다.Fox Query 는 수행할 쿼리를 찾기 위한 쿼리 ID를 매개변수로 사용하며 이 쿼리 ID에서 읽어야 할
.foxml파일과.foxml파일 내의 쿼리를 알아냅니다.Fox Query 를 수행할 때 전달되는 DB 매개변수는
ExecuteSql-,ExecuteSp-등의 다른 메서드들과는 차이점이 있습니다. Fox Query 의 DB 매개변수에 대해서는 Fox Query DB 매개변수 항목을 참고 하십시요. -
-Command-: 매개변수로 주어진Command객체를 수행합니다. 이 메서드는CreateCommand메서드에 의해 생성된Command객체나 Fox DB Access 가 아닌 다른 API 를 통해 생성된Command객체를 매개변수로 사용합니다.
수행 결과 접미사 ¶
두번째 접미사는 Execute- 시리즈 메서드가 반환하는 반환값을 나타냅니다. 이 접미사는 항상 수행할 커맨드 종류를 나타내는 접미사 뒤에만 사용됩니다.
-
-DataSet: 수행 결과를DataSet객체에 담아 반환합니다. 전형적으로SELECT문장(들)을 수행하고 그 결과셋(resultset)을 반환합니다.DataSet객체에 포함된DataTable객체의 이름(DataTable.TableName속성)은Table이며FoxDbAccess클래스의DefaultTableName속성으로 변경할 수 있습니다. -
-List<T>: 수행 결과를List<T>객체로 반환합니다. 결과셋은T타입으로 매핑 됩니다. 대개SELECT류의 문장을 수행하고 그 결과를 담는T타입의 객체 목록을 획득하는데 사용됩니다. 예를 들어, 다음 예제는 SELECT 문장으로 읽은 데이터를Product객체에 매핑하여List<Product>컬렉션으로 반환합니다. -
-NonQuery: 수행 결과를 반환하지 않습니다.INSERT,UPDATE,DELETE류의 문장을 수행하거나 저장 프로시저를 호출할 때 사용합니다.INSERT/UPDATE/DELETE류의 명령이 영향 받은 행(row) 개수를 정수값으로 반환합니다.Note
PostgreSQL 은 Npgsql 의 버전에 따라 항상 -1 을 반환하는 경우도 있습니다.
-
-Scalar: 수행 결과를 스칼라(scalar) 값으로 반환합니다. 즉, SQL 문장 혹은 저장 프로시저가 반환한 결과셋에서 첫번째 행, 첫번째 열을 스칼라 값으로 반환합니다. 나머지 결과셋은 무시됩니다.Note
스칼라 값을 반환하는 경우 데이터베이스마다 반환되는 타입이 다를 수 있습니다. 예를 들어
SELECT COUNT(*) FROM ...값은 PostgreSQL 은 long 타입(Int64)으로 반환되지만 Oracle 은 decimal 타입으로 반환됩니다. 따라서 단순한 형변환은 데이터베이스에 따라 오류를 유발할 수 있습니다. 안전한 변환은Convert클래스가 제공하는ToXXX메서드를 사용하는 것입니다. -
-Reader: 수행 결과를DataReader객체로 반환합니다. 결과셋을 반환하는 SQL 문장 혹은 저장 프로시저를 수행하고 그 결과셋을 나타내는DataReader객체를 반환합니다.FoxDbAccess가 제공하는ExecuteXXXReader메서드들은 가장 전형적으로DataReader를 사용하는 패턴을 지원하고자자CommandBehavior설정으로 기본값(None)을 사용합니다. 다른CommandBehavior설정을 사용하여DataReader를 사용하고자 한다면FoxDbAccess클래스의CreateCommand메서드를 호출하여Command객체를 생성하고 원하는CommandBehavior설정을 사용하여ExecuteReader메서드를 호출하십시요.Note
Command.ExecuteReader메서드는 FoxDbAccess 에 의해 제어되지 않으므로 데이터베이스 연결을 자동으로 열어주지 않습니다. 따라서 위 코드에서는 명시적으로Open메서드를 호출하고try~finally문장에 의해Close메서드를 호출합니다.FoxDbAccess의 연결 관리에 대한 상세한 내용은 연결 관리 문서를 참고 하십시요. -
-: 접미사가 없는 메서드는DataSet객체를 매개변수로 받고 SQL 문장 혹은 저장 프로시저를 수행한 결과셋으로 주어진DataSet객체를 채워넣습니다(fill). 여러개의 쿼리 결과를 하나의DataSet객체에 담거나 여러 데이터베이스의 쿼리 결과를 하나의DataSet객체에 담고자하는 경우에 유용합니다. 다음 예제는 PostgreSQL 과 Oracle 에SELECT문을 수행하고 하나의DataSet에 채워 넣는 코드 입니다.Note
위 예제 코드에서
ExecuteSql메서드 호출은 테이블 이름 매핑(mapping)을 사용합니다. 접미사가 없는Execute-메서드들은 내부적으로DataAdapter.Fill메서드를 호출하며 이 메서드는 테이블 이름 매핑이 사용되지 않는 경우DataSet의 첫번째DataTable에 결과를 채웁니다. 따라서 테이블 이름 매핑을 사용하지 않으면 두ExecuteSql메서드 호출은 하나의DataTable에 병합(merge)됩니다. 테이블 이름 매핑에 대한 상세한 내용은 이 문서에서 다시 상세히 언급됩니다.Note
접미사가 없는
Execute-메서드는 과거 .NET Framework 2.x 시절부터 TypedDataSet지원을 위한 메서드이기도 합니다. TypedDataSet은 최근에는 거의 사용하지 않는 데이터 컨테이너 입니다.
Execute- 메서드의 매개변수들¶
Execute- 시리즈 메서들에서 사용되는 여러 매개변수들에 대한 설명입니다. Execute- 메서드들은 매우 다양하기 때문에 사용하는 매개변수들도 매우 다양합니다. 여기서 설명되는 매개변수들은 Execute- 메서드들에 따라서 적용되는 여부가 달라질 수 있습니다.
수행 대상 매개변수¶
Exeucte 시리즈 메서드들의 첫번째 매개변수는 수행 대상을 나타내는 -Sql-, -Sp, -Query-, -Command- 접미사들과 연관이 있습니다.
ExecuteSql-메서드들의 첫번째 매개변수는 수행할 SQL 문장 입니다.ExecuteSp-메서드들의 첫번째 매개변수는 수행할 저장 프로시저의 이름입니다.ExecuteQuery-메서드들의 첫번째 매개변수는 수행할 Fox Query 에 대한 쿼리 ID 입니다.ExecuteCommand-메서드들의 첫번째 매개변수는 수행할Command객체 입니다.
DB 매개변수¶
ExecuteQuery- 메서드들과 일부 ExecuteCommand- 메서드를 제외한 Execute- 시리즈 메서드들은 SQL 문장/저장 프로시저에 적용할 DB 매개변수를 사용할 수 있습니다. 예를 들어, FoxDbAccess 클래스는 SQL 문장을 수행하여 DataSet 객체를 반환하는 ExecuteSqlDataSet 메서드를 다음과 같이 정의합니다.
SQL Server 를 위한 SqlParameter, Oracle 을 위한 OracleParameter, PostgreSQL 을 위한 NpgsqlParameter 등의 타입들들은 모두 IDataParameter 인터페이스를 구현하는 DbParameter 타입에서 파생되었습니다. 따라서 이들 타입에 대한 IEnumerable<IDataParameter> 를 지원하는 배열, 리스트(List<T>) 등의 타입을 모두 사용할 수 있습니다.
배열이나 리스트를 사용하는 것보다 편리한 기능들을 갖는 FoxDbParamerCollection 객체를 사용하는 것이 더 권장됩니다. FoxDbParamerCollection 및 그 파생 클래스들(FoxSqlParameterCollection, FoxOracleParameterCollection, FoxNpgsqlParameterCollection 등)은 AddWithValue 메서드를 통해 컬렉션에 DB 매개변수를 손쉽게 추가할 수 있으며 null 값을 DBNull.Value 로 자동으로 변환하는 기능을 제공합니다. FoxDbParameterCollection 클래스는 IEnumerable<IDataParameter> 인터페이스를 구현하기 때문에 Execute- 시리즈 메서드에 사용할 수 있습니다. 더욱이 FoxDbParameterCollection 타입은 특정 데이터베이스에 의존적이지 않은 추상 클래스이므로 데이터베이스에 의존성이 없는 FoxDbAccess 클래스와 사용하기 적합합니다.
ExecuteCommand- 메서드들 중 일부는 IEnumerable<IDataParameter> 매개변수를 사용하지 않습니다. ExecuteCommand- 메서드는 CreateCommand 메서드나 Fox DB Access 를 사용하지 않고 다른 방법으로 생성된 Command 객체를 수행하는 메서드 입니다. 이렇게 생성된 Command 객체는 데이터베이스 매개변수에 대한 설정이 이미 완료되기 때문에 ExecuteCommand- 메서드에서 IEnumerable<IDataParameter> 매개변수가 포함되지 않는 것입니다.
Note
위 코드에서 CreateCommand 메서드 호출과 ExecuteCommand 메서드 호출을 한번에 호출하는 단축(short-cut) 메서드에서는 IEnumerable<IDataParameter> 매개변수가 포함될 수도 있습니다. 이 경우 첫번째 매개변수가 Command 객체가 아닌 CommandText 문자열(SQL 문장 혹은 저장 프로시저 이름)이 됩니다.
Fox Query 의 DB 매개변수 ¶
Fox Query 를 수행하는 메서드의 DB 매개변수는 작동 방식이 다릅니다. Fox Query 는 .foxml 파일에 SQL 문장 뿐만 아니라 매개변수 정보들도 기록해 두기 때문에 ExecuteQuery- 메서드들이 수행될 때 DB 매개변수들도 이 정보를 사용하여 자동으로 생성됩니다.
예를 들어, 다음과 같은 Fox Query 파일(.foxml) 의 <statement> 태그가 있을 때 <parameters> 태그는 Command 객체의 Parameters 컬렉션에 DB 매개변수들을 설정합니다. 이 예제의 경우 product_id, product_name 이라는 이름을 가진 DB 매개변수가 생성됩니다.
Information
ExecuteQueryDataSet 메서드가 수행하는 과정을 FoxDbAccess 가 제공하는 Fox Query 관련 API 들로 풀어서 다시 작성해보면 다음과 같습니다.
위 코드를 통해 Command 객체를 생성할 때 DB 매개변수가 이미 구성되어 있다는 것을 알 수 있습니다.
DB 매개변수가 이미 설정되어 있으므로 ExecuteQuery- 메서드를 수행하기 위해서는 DB 매개변수의 값(들)만을 전달하면 됩니다. 따라서 ExecuteQuery- 메서드에서는 DB 매개변수가 아닌 DB 매개변수 값(들)을 전달해야 합니다.
ExecuteQuery- 메서드의 parameterObject 매개변수에 사용할 수 있는 객체는 다음과 같습니다.
-
IDictionary객체DB 매개변수 컬렉션에서 매개변수 이름에 대응되는
IDictionary키/값을 찾아 DB 매개변수 값으로 사용합니다. Fox Biz/Data Service Web API 에서 사용되는 매개변수 컬렉션이IDictionary를 사용하므로 이 때 많이 사용됩니다. -
DataRow객체DB 매개변수 컬렉션에서 매개변수 이름에 대응되는
DataRow컬럼을 찾아 그 값을 설정합니다.DataTable의 변경 사항을 일괄적으로 추가/수정/삭제 할 때 많이 사용됩니다. -
일반 닷넷 객체
DB 매개변수 컬렉션에서 매개변수 이름에 대응되는 객체의 속성/필드를 찾아 그 값을 설정합니다. 엔티티 기반 앱에서 사용하거나 익명 타입(anonnymous type)을 사용하여 간단한 구현에 사용합니다.
테이블 이름 매핑(mapping)¶
수행한 SQL 문장 혹은 저장 프로시저가 여러 테이블을 반환하는 경우 DataSet 객체는 여러 DataTable 객체를 포함하게 됩니다. 여러 DataTable의 이름은 기본적으로 DefaultTableName 속성값을 사용하고 뒤에 숫자가 붙는 형태로 적용됩니다. DefaultTableName 속성을 변경하지 않았다면 DataTable 의 이름들은 Table, Table1, Table2 등이 됩니다.
DefaultTableName 속성값을 ResultSet 으로 변경했다면 DataSet에 포함된 DataTable의 이름들은 ResultSet, ResultSet1, ResultSet2 가 됩니다.
-DataSet 접미사를 사용하는 Execute- 메서드들은 앞서 언급한 방식이외에도 DataTable 의 이름을 임의로 지정가능한 매핑 정보를 매개변수로 사용할 수 있습니다.
테이블 이름 매핑 정보가 주어지면 DataTable 의 이름은 테이블 이름 매핑 정보에 의해 지정됩니다.
외부 커맨드 수행 ¶
가끔씩 FoxDbAccess 클래스를 통해 Execute- 메서드들을 수행하기 어렵거나 FoxDbAccess 가 제공하는 CreateCommand 메서드를 사용하기 어려울 때가 있을 수 있습니다. 예를 들어 CommandBuilder 클래스를 통해 INSERT/UPDATE/DELETE 문장을 포함하는 Command 객체를 사용하고자 하는 상황입니다. 다음 예제는 CommandBuilder 클래스를 통해 INSERT SQL 문장을 포함하는 커맨드 객체를 생성하고 수행하는 예를 보여 줍니다.
Fox DB Access 가 아닌 외부 API 를 통해 생성된 Command 객체를 FoxDbAccess 클래스를 통해 수행할 때 얻을 수 있는 장점은 FoxDbAccess 객체가 제공하는 연결 관리 기능, 트랜잭션 처리 기능의 적용을 받을 수 있으며 해당 Command 객체에 대한 DB 프로파일 정보도 같이 얻을 수 있기 때문입니다.
Summary¶
Fox DB Access 는 SQL 문장을 수행하거나 저장 프로시저를 편리하게 호출하기 위해 매우 다양한 Execute- 메서드들을 제공합니다. SQL 문장을 수행하기 위한 ExecuteSql- 메서드들, 저장 프로시저 호출을 위한 ExecuteSp- 메서드들을 비롯하여 .foxml 파일에서 Fox Query 를 읽어 들어 수행하는 ExecuteQuery- 메서드들과 다양한 방법을 통해 생성된 Command 객체를 수행하는 ExecuteCommand- 메서드들도 제공됩니다.
이들 메서드들은 쿼리 수행 결과로서 DataSet 객체, 스칼라 값, DataReader 객체를 반환하거나 쿼리 수행 결과를 무시할 수도 있습니다.
각 Execute- 메서드들은 수행하고자 하는 대상(SQL 문장, 저장 프로시저, Fox Query 등)과 수행 결과(DataSet, DataReader 등)에 따라 매개변수, 작동 방식에서 약간의 차이점이 있지만 이 문서에서 설명한 내용을 숙지하면 사용하는데 어려움은 없을 것입니다. 이들 Execute- 메서드들을 통해 개발자는 전통적인 데이터 액세스 방법보다 훨씬 더 적은 노력과 시간으로 보다 데이터 액세스를 수행할 수 있습니다.