Fox Data Service 기본 사용법¶
Fox Data Service 는 FoxDataService 클래스에 의해 제공되는 데이터 액세스 서비스입니다. FoxDataService 클래스는 Fox Query 를 사용하여 데이터베이스를 액세스하는 기능을 캡슐화한 클래스입니다. 클라이언트는 호출할 Fox Query 의 ID 와 매개변수를 포함하는 FoxDataRequest 객체를 매개변수로 FoxDataService 클래스의 ExecuteXXX 시리즈 메서드를 호출하여 쿼리를 실행하고 그 결과를 FoxDataResponse 객체를 통해 받을 수 있습니다.
Information
개발자가 직접 FoxDataService 클래스의 인스턴스를 생성하여 사용하는 경우는 많지 않습니다. 일반적으로 Fox Web API 나 WCF, gRPC 와 같은 통신 서비스에서 Fox Data Service 를 사용하여 클라이언트의 요청을 처리하는 방법이 가장 일반적입니다. Fox Data Service 를 ASP.NET Web API (Fox Web API) 를 통해 호출하는 방법은 별도의 문서에서 설명합니다. 이 문서에서 설명하는 전체 내용은 모두 Fox Web API 를 통해서 호출할 때에도 동일하게 적용할 수 있습니다. 다만 여러분의 코드가 Fox Data Service 를 직접 생성하여 호출하느냐 아니면 Fox Web API 가 Fox Data Service 를 자동으로 구성하고 호출하는가의 차이만 있을 뿐입니다.
시작하기¶
Fox Data Service 를 사용하기 위해서는 NeoDEEX.ServiceModel.Services 패키지를 참조해야 합니다. 이 패키지에는 Fox Data Service 와 Fox Biz Service 를 구현하는 클래스들이 포함되어 있습니다. FoxDataService 클래스는 NeoDEEX.ServiceModel.Services.Data 네임스페이스에 포함되어 있습니다.
Information
Fox Data Service 는 Fox Web API 를 통해서 호출하는 것이 대부분이므로 Fox Web API 를 구현하는 NeoDEEX.ServiceModel.WebApi 패키지를 참조하면 자동으로 NeoDEEX.ServiceModel.Services 패키지도 참조됩니다. 따라서 Fox Web API 를 구현하는 경우에는 별도로 NeoDEEX.ServiceModel.Services 패키지를 참조할 필요가 없습니다.
Fox Web API 없이 직접 Fox Data Service 를 사용하는 경우, FoxDataService 클래스의 인스턴스를 생성하여 ExecuteXXX 시리즈 메서드를 호출할 수 있습니다. 다음 코드는 ASP.NET Core Razor 페이지에서 Fox Data Service 를 사용하여 orders.foxml 파일의 get_all_orders_with_details 쿼리를 호출하여 결과를 HTML 로 렌더링하는 예를 보여줍니다.
서비스 객체 생성¶
FoxDataService 클래스는 매개변수가 없는 디폴트 생성자만을 제공하지만 대신 Fox Data Service 의 작동 방식을 설정하는 다양한 public 속성들을 제공합니다. Fox Data Service 가 ASP.NET Web API 나 WCF, gRPC 와 같은 다양한 통신 서비스에 의해 사용되며 개발자가 직접 FoxDataService 클래스의 인스턴스를 생성하는 경우가 많지 않기 때문입니다. 대신 구성 설정 파일(neodeex.config.json 파일)에서 이들 public 속성들의 기본값을 설정할 수 있습니다.
예를 들어, 다음 코드와 같이 FoxDataService 클래스의 인스턴스를 생성할 때 EnableDiagnostics 속성을 true로 설정하고 LoggerName 속성을 지정하면, 나머지 FoxDataService 속성들은 기본값이 적용되거나, neodeex.config.json 구성 설정의 "dataService" 섹션에서 설정된 값이 적용됩니다. Fox Data Service 의 구성 설정에 대한 자세한 내용은 구성 설정 항목을 참조하십시요.
-
LoggerName속성FoxDataService클래스가 로그를 기록할 때 사용할 로거의 이름을 지정하는 속성입니다. 아무런 설정이 없는 경우 이 속성의 기본값은NeoDEEX.ServiceModel.Data.FoxDataService입니다.LoggerName속성이 지시하는 이름의 로거가 구성되지 않은 경우 로그는 기록되지 않습니다. -
EnableDiagnostics속성FoxDataService클래스가 제공하는 다양한 진단 기능들을 켜거나 끌 수 있는 속성입니다. 진단 기능에는 쿼리 수행 시간 측정, 로그 반환, 상세한 예외 정보, 로그 ID 등이 포함됩니다. 상세한 내용은 성능 로깅과 DB 프로파일 로깅을 참조하십시요. 아무런 구성 설정이 없는 경우, 이 속성의 기본값은false입니다.Warning
이 속성은 서비스가 생성하는 서버 측 로그를 제어하지 않습니다. 서비스가 생성하는 서버 측 로그는
LoggerName속성이 지정하는 로거의 존재 유무 그리고 로그 필터링 수준에 의해서만 제어됩니다. -
EnableDetailedDbProfile속성FoxDataService클래스의ExecuteXXX시리즈 메서드들은 쿼리를 수행하고 결과를 반환할 때 DB 프로파일 정보를FoxDataResponse객체에 반환할 수 있습니다.FoxDataRequest객체의Diagnostics속성에FoxDataRequestDiagnostics.DbProfileInfo값이 지정되면 Fox Data Service 는 Fox Query 를 수행하면서 DB 프로파일 정보를 수집하고 그 결과를FoxDataResponse객체의DbProfileInfo속성에 기록하여 반환합니다. DB 프로파일 정보와 같은 성능 로깅에 대한 상세한 설명은 성능 측정 항목을 참조하십시요.DB 프로파일 정보에는 쿼리에 사용된 SQL 문장과 매개변수 값 등 민감한 정보가 포함될 수 있습니다. 따라서 이 속성이
true로 설정된 경우에만 모든 정보를 반환하며false로 설정된 경우에는 SQL 문장이나 매개변수 값 등 민감한 정보가 제외된 DB 프로파일 정보만 반환합니다. 아무런 구성 설정이 없는 경우 이 속성의 기본값은false입니다.개발 서버의 경우 이 속성을
true로 설정하여 DB 프로파일 정보를 활용한 진단을 수행할 수 있지만, 운영 서버의 경우 이 속성을false로 설정하여 SQL 문장, Fox Query 파일의 전체 경로 등 민감한 정보가 노출되는 것을 방지하는 것이 좋습니다.EnableDiagnostics속성이false로 설정된 경우에는 이 속성의 값과 무관하게 DB 프로파일 정보가 반환되지 않습니다. -
EnablePerfLog속성FoxDataService클래스는 쿼리를 수행하는데 소요되는 시간을 측정하여 로그에 기록할 것인지 여부를 지정하는 속성입니다. 이 속성이true로 설정된 경우, 성능 로그가PerfLoggerName속성이 지정하는 로거에 기록합니다. 아무런 구성 설정이 없는 경우 이 속성의 기본값은false입니다. -
PerfLoggerName속성FoxDataService클래스가 성능 로그를 기록할 때 사용할 로거의 이름을 지정하는 속성입니다. 이 속성은EnablePerfLog속성이true로 설정된 경우에만 적용됩니다. 아무런 구성 설정이 없는 경우 이 속성의 기본값은NeoDEEX.ServiceModel.Data.FoxDataService.Performance입니다.
구성 설정¶
Fox Data Service 에 대한 구성 설정은 neodeex.config.json 파일의 최상위 "dataService" 섹션에서 다음과 같이 설정할 수 있습니다.
-
commandTimeout속성commandTimeout속성은 Fox Data Service 가 쿼리를 수행할 때 사용할 기본 쿼리 타임 아웃을 초 단위로 지정하는 속성입니다. 이 속성이 설정되지 않았거나null로 설정된 경우, 연결 문자열에 설정된 타임 아웃 값이 사용됩니다. 물론 이러한 "기본 설정 값"은FoxDataRequest객체의CommandTimeout속성에서 개별 쿼리 호출 시에 오버라이드할 수 있습니다. -
transactionTimeout속성transactionTimeout속성은 Fox Data Service 가 트랜잭션을 시작할 때 사용할 기본 트랜잭션 타임 아웃을 초 단위로 지정하는 속성입니다. 이 속성이 설정되지 않았거나null로 설정된 경우, 60초의 값이 사용됩니다. 물론 이러한 "기본 설정 값"은FoxDataRequest객체의TransactionTimeout속성에서 개별 쿼리 호출 시에 오버라이드할 수 있습니다. -
diagnostics속성서비스 객체 생성 항목에서 설명한
LoggerName,EnableDiagnostics,EnableDetailedDbProfile속성은 이diagnostics속성의 하위 속성으로 설정할 수 있습니다. 이들 하위 속성의 이름은 각각loggerName,enable,detailedDbProfile입니다. -
perfLog속성서비스 객체 생성 항목에서 설명한
EnablePerfLog,PerfLoggerName속성은 이perfLog속성의 하위 속성으로 설정할 수 있습니다. 이들 하위 속성의 이름은 각각enable,loggerName입니다.
기본 ExecuteXXX 메서드들¶
FoxDataService 클래스는 FoxDbAccess 클래스와 유사하게 ExecuteXXX 시리즈 메서드들을 제공합니다. ExecuteXXX 시리즈 메서드들은 하나의 쿼리를 수행하는 단일 쿼리 메서드들과 여러 개의 쿼리를 수행하는 다중 쿼리 메서드들로 나눌 수 있습니다. 단일 쿼리 메서드들은 FoxDataRequest 객체를 매개변수로 받아 하나의 쿼리를 수행하는 반면, ExecuteMultiple 과 같은 다중 쿼리 메서드들은 FoxDataRequest 객체의 컬렉션을 매개변수로 받아 여러 개의 쿼리를 배치로 수행하며 그 결과는 FoxDataResponse 객체의 컬렉션으로 반환합니다. 다중 쿼리 메서드들은 Fox Data Service 의 고급 사용법 문서에서 설명하겠습니다.
단일 쿼리 메서드들은 하나의 FoxQuery 를 수행하는 메서드들입니다. 따라서 FoxDataRequest 객체의 QueryId 속성에 하나의 쿼리 ID 를 지정하며 매개변수는 Parameters 속성에 지정합니다. 쿼리에 사용할 데이터베이스 연결 문자열의 이름을 DatabaseName 속성에 지정할 수도 있습니다.
-
ExecuteDataSet메서드FoxDataRequest객체의 쿼리를 실행하여 결과를DataSet형태로 반환하는 메서드입니다. 반환된DataSet객체는FoxDataResponse객체의DataSet속성에 포함되어 반환됩니다.SELECT문과 같은 결과셋을 반환하는 쿼리를 수행하는데 사용합니다. -
ExecuteScalar메서드Command객체의ExecuteScalar메서드와 유사하게FoxDataRequest객체의 쿼리를 실행하여 결과셋의 첫 번째 행의 첫 번째 열의 값을 반환하는 메서드입니다. 반환된 값은FoxDataResponse객체의ScalarValue속성에 포함되어 반환됩니다.SELECT COUNT(*)문과 같은 단일 값을 반환하는 쿼리를 수행하는데 사용합니다. -
ExecuteNonQuery메서드Command객체의ExecuteNonQuery메서드와 유사하게FoxDataRequest객체의 쿼리를 실행하여 영향받은 행 수를 반환하는 메서드입니다. 반환된 영향받은 행 수는FoxDataResponse객체의AffectedRows속성에 포함되어 반환됩니다.INSERT,UPDATE,DELETE문과 같은 데이터 변경 쿼리를 수행하는데 사용합니다. -
Execute메서드FoxDataRequest객체의Operation속성 값에 따라ExecuteXXX시리즈 메서드들 중 하나를 호출하는 메서드입니다.Operation속성 값이DataSet,Scalar,NonQuery,SaveDataTable인 경우 각각ExecuteDataSet,ExecuteScalar,ExecuteNonQuery,SaveDataTable메서드를 호출합니다. 이 메서드는 클라이언트가 실행할 쿼리의 유형을 동적으로 지정해야 하는 시나리오에서 유용합니다.
SaveDataTable 메서드¶
SaveDataTable 메서드도 하나의 FoxDataRequest 객체를 매개변수로 받아 하나의 쿼리를 수행하는 단일 쿼리 메서드입니다. 하지만, 이 메서드는 매개변수로 주어진 DataTable 객체에서 각 행의 RowState에 따라 여러 추가/수정/삭제된 행들을 데이터베이스에 저장하는 메서드입니다. 데스크 톱 앱에서 DataTable 객체를 바인딩하여 사용자가 그리드에서 데이터를 추가/수정/삭제할 수 있도록 하는 시나리오에서 유용합니다. 데이터그리드 컨트롤에서 추가/수정/삭제된 데이터를 GetChanges 메서드를 사용하여 DataTable 객체로 가져와서 SaveDataTable 메서드에 전달하여 변경된 여러 개의 행을 한 번에 저장할 수 있습니다.
SaveDataTable 메서드를 사용하는 구체적인 예제 코드는 다음을 참고 하십시요.
Note
위 예제 코드는 WinForms 데스크톱 앱에서 FoxDataServiceClient 클래스 를 활용하여 원격 Fox Data Service 를 Web API 로 호출하는 예제입니다.
추가/수정/삭제에 사용할 쿼리 ID 는 FoxDataRequest 객체의 InsertQueryId, UpdateQueryId, DeleteQueryId 속성에 각각 지정합니다. 저장에 사용할 DataTable 객체는 FoxDataRequest 객체의 DataSet 속성에 DataSet 형태로 지정합니다.
SaveDataTable 메서드는 저장이 성공적으로 완료된 후에 저장한 행 수를 반환합니다. 반환된 저장된 행 수는 FoxDataResponse 객체의 AffectedRows 속성에 포함되어 반환됩니다.
저장 후 조회¶
QueryId 속성이 null 이나 빈 문자열이 아닌 경우, QueryId 속성과 Parameters 속성은 저장 후 조회(ExeucteDataSet 메서드)를 수행하는데 사용됩니다. 저장 후 조회는 SaveDataTable 메서드가 DataTable 객체의 변경된 내용을 데이터베이스에 저장한 후, 지정된 QueryId에 해당하는 쿼리를 다시 실행하여 데이터베이스에 저장된 최신 데이터를 반환하는 기능입니다. 이 기능은 클라이언트가 DataTable 객체의 변경된 내용을 데이터베이스에 저장한 후, 데이터베이스에 저장된 최신 데이터를 다시 조회해야 하는 시나리오에서 유용합니다. 위 예제 코드에서도 변경 사항을 저장한 후에 products.get_all 쿼리를 다시 호출하여 데이터베이스에 저장된 최신 데이터를 조회하고 그 결과를 ProductsGridView 컨트롤에 바인딩합니다.
저장 모드¶
SaveDataTable 메서드가 여러 행의 추가/수정/삭제를 처리하는 방식은 3가지 모드 중 하나로 지정할 수 있습니다. 이 저장 모드는 FoxDataRequest 객체의 SaveMode 속성에 FoxDataSaveModes 열거 타입을 사용하여 지정합니다.
-
LoopUpdate모드SaveDataTable메서드의 기본 저장 모드이며,DataTable에서 변경된 행들을 그룹화하여 업데이트할 때 반복문(foreach)을 사용합니다. 삭제, 수정, 추가 순서로 변경된 행들을 처리합니다. 안정적이지만 다수의 행을 처리해야 한다면 성능이 좋지 않을 수 있습니다. -
BatchUpdate모드ADO.NET 의
DataAdapter클래스의Update메서드를 사용하여 일괄 업데이트를 수행하는 저장 모드입니다. 데이터베이스 프로바이더 구현에 따라서Update메서드는 여러 수정사항을 배치로 처리할 수 있기 때문에 다수의 행을 처리해야 할 때 성능상 장점을 가질 수 있습니다. 하지만DataAdapter.Update메서드에 의존하므로 데이터베이스 프로바이더의 구현에 따라 성능 차이가 발생할 수 있으며, 데이터 저장 순서 역시 프로바이더에 따라 달라질 수 있습니다. -
GroupedBatchUpdate모드BatchUpdate모드와 동일하게 ADO.NET 의DataAdapter클래스의Update메서드를 사용하여 일괄 업데이트를 수행하지만,LoopUpdate모드와 같이 삭제, 수정, 추가 순서로 변경된 행들을 처리하는 저장 모드입니다. 즉, 배치 업데이트를 삭제, 수정, 추가 3회를 수행합니다.BatchUpdate모드에 비해 안정적인 저장 순서를 보장하지만, 데이터베이스 프로바이더의 구현에 따라 사용 가능 여부, 성능 등이 결정됩니다.
Warning
BatchUpdate 모드와 GroupedBatchUpdate 모드는 데이터베이스 프로바이더의 DataAdapter.Update 메서드와 DataAdapter.UpdateBatchSize 속성에 의존합니다. 하지만 모든 데이터베이스 프로바이더가 DataAdapter.Update 메서드에서 일괄 업데이트를 지원하는 것은 아니며, Npgsql 과 같은 데이터 프로바이더는 DataAdapter.UpdateBatchSize 속성에 대해 NotSupportedException 예외를 유발합니다. 따라서 BatchUpdate 모드와 GroupedBatchUpdate 모드를 사용할 때는 데이터베이스 프로바이더가 일괄 업데이트를 지원하는지 여부를 확인하는 것이 좋습니다. SQL Server 와 Oracle 데이터베이스는 배치 업데이트를 지원하므로 성능적으로 우수한 배치 업데이트를 수행할 수 있습니다. 호환성이 중요하다면 배치 업데이트를 사용하지 않는 것이 좋습니다.
트랜잭션 고려 사항¶
기본적으로 SaveDataTable 메서드는 트랜잭션을 사용하지 않으며, 저장 도중 오류가 발생하면 즉시 수행을 중단하고 반환합니다. FoxDataRequest 객체의 Transaction 속성에 트랜잭션 모드를 지정하여 트랜잭션을 사용하는 경우, 저장 도중 오류가 발생하면 전체 저장 작업이 롤백됩니다.
Summary¶
Fox Data Service 는 FoxDataService 객체를 생성하고 수행하고자 하는 Fox Query 의 정보를 담는 FoxDataRequest 객체를 매개변수로 ExecuteXXX 시리즈 메서드를 호출하여 쿼리를 수행하고 그 결과를 FoxDataResponse 객체를 통해 반환받는 방식으로 동작합니다. Fox Data Service 를 제어하는 다양한 기능은 FoxDataService 클래스의 public 속성들을 통해 제어할 수 있으며, 이러한 속성들은 neodeex.config.json 구성 설정 파일의 "dataService" 섹션에서 기본값을 설정할 수도 있습니다.
이외에도 SaveDataTable 메서드를 사용하면 DataTable 객체에서 변경된 여러 행들을 한 번에 저장할 수 있으며, 저장 후 조회 기능을 통해 데이터베이스에 저장된 최신 데이터를 다시 조회할 수도 있습니다.