Skip to content

Fox Data Service 고급 사용법

Fox Data Service 는 단순히 하나의 Fox Query 를 실행하는 기능 뿐만 아니라 여러 쿼리를 배치로 수행하는 다중 쿼리(ExecuteMultiple), 단일 혹은 다중 쿼리에 대한 로컬/분산 트랜잭션 기능, 예외 처리 기능, 로깅/쿼리 성능 측정 등을 포함하는 다양한 진단 기능 등을 제공합니다. 이 문서는 Fox Data Service 의 이러한 고급 기능들을 사용하는 방법에 대해 설명합니다.

ExecuteMultiple 메서드

ExecuteMultiple 메서드는 FoxDataRequestCollection 객체 를 매개변수로 받아 여러 개의 쿼리를 배치로 수행하는 메서드입니다. FoxDataRequestCollection 객체는 여러 개의 FoxDataRequest 객체를 포함할 수 있으며, 각 FoxDataRequest 객체는 하나의 쿼리를 나타냅니다. ExecuteMultiple 메서드는 이들 쿼리를 "순차적"으로 모두 수행하여 그 결과를 FoxDataResponseCollection 객체로 반환합니다. 반환된 FoxDataResponseCollection 객체는 여러 개의 FoxDataResponse 객체를 포함할 수 있으며, 각 FoxDataResponse 객체는 하나의 쿼리 수행 결과를 나타냅니다.

다음 코드는 ExecuteMultiple 메서드를 사용하여 주문과 주문 상세 정보를 각각 조회하는 두 개의 쿼리를 배치로 수행하는 예를 보여줍니다.

FoxDataRequestCollection requests = new(String.Empty)
{
    new FoxDataRequest("orders.get_order_by_id") { Operation = FoxDataOperations.ExecuteDataSet },
    new FoxDataRequest("orders.get_details_by_id") { Operation = FoxDataOperations.ExecuteDataSet },
};
requests[0].Parameters["order_id"] = 1;
requests[1].Parameters["order_id"] = 1;
FoxDataResponseCollection responses = dataService.ExecuteMultiple(requests);
DataRow orderRow = responses[0].DataSet.Tables[0].Rows[0];
DataTable detailsTable = responses[1].DataSet.Tables[0];

Note

위 예제 코드는 ExecuteMultiple 메서드를 사용하는 예를 보이기 위한 코드입니다. 실제로는 하나의 쿼리에서 두 개의 SELECT 문을 사용하여 주문과 주문 상세 정보를 한 번에 조회하는 쿼리를 작성하여 ExecuteDataSet 메서드를 호출하는 것이 더 효율적입니다.

컬렉션에 포함된 두 개의 FoxDataRequest 객체는 쿼리를 수행할 QueryId, Parameters 속성들 외에도 Operation 속성에 FoxDataOperations 열거 타입의 값 중 하나의 값을 지정하여 각 쿼리를 수행할 때 사용할 ExecuteXXX 메서드를 지정해야 합니다. Operation 속성 값이 지정되지 않은 경우, ExecuteMultiple 메서드는 InvalidOperationException 예외를 유발합니다. Operation 속성에 대한 상세한 내용은 ExecuteMultiple 관련 속성 항목을 참조하십시오.

단일 데이터베이스 연결

ExecuteMultiple 메서드는 모든 쿼리를 하나의 데이터베이스 연결을 통해 수행하거나 개별 쿼리마다 사용할 데이터베이스 연결을 지정할 수 있습니다. 하나의 연결을 사용하는 경우, FoxDataRequestCollection 객체의 DatabaseName 속성에 null 이 아닌 연결 문자열의 이름을 지정합니다. 빈 연결 문자열 이름(String.Empty)은 구성 설정의 디폴트 연결 문자열 이름이 사용됩니다(Fox DB Access 의 연결 정보 선택 참조). 개별 FoxDataRequest 객체의 DatabaseName 속성은 무시됩니다. 따라서 컬렉션에 포함된 모든 쿼리는 동일한 데이터베이스 연결을 사용하여 수행됩니다.

ExecuteMultiple 예제 코드에서는 빈 연결 문자열 이름을 사용하여 구성 설정의 디폴트 연결 문자열이 사용하여 모든 쿼리를 수행합니다. 다음 로그는 ExecuteMultiple 메서드가 하나의 연결을 사용하여 두 개의 쿼리를 수행할 때 Fox Data Service 가 생성하는 로그를 보여줍니다.

>> Data Service Start: ExecuteMultiple  Requests=2  UserId=  ClientMachine=  ClientIP=
    & Using COLLECTION scope dbaccess(<default>)
    & EXPLICITLY Open Database Connection...
    Start Processing Request[0]
    Before Invoke: DbAccess.ExecuteDataSet()  qid=orders.get_order_by_id  in-param=1
    After Invoke: DbAccess.ExecuteDataSet()  elpased = 12.9 msec
    End Processing Request[0]  elapsed = 13.2 msec
    Start Processing Request[1]
    Before Invoke: DbAccess.ExecuteDataSet()  qid=orders.get_details_by_id  in-param=1
    After Invoke: DbAccess.ExecuteDataSet()  elpased = 4.4 msec
    End Processing Request[1]  elapsed = 4.5 msec
    & EXPLICITLY Close Database Connection...
>> Data Service End: ExecuteMultiple  elapsed = 19.1 msec

이 로그에서 하나의 FoxDbAccess 인스턴스가 생성되고 하나의 데이터베이스 연결이 열렸다가 두 개의 쿼리를 수행한 후 닫히는 것을 확인할 수 있습니다.

개별 데이터베이스 연결

여러 데이터베이스에 대해 여러 쿼리를 한번에 수행해야 하는 경우 ExecuteMultiple 메서드를 사용하면 편리합니다. 개별 쿼리마다 연결을 명시하려면, FoxDataRequestCollection 객체의 DatabaseName 속성에 null 값을 지정하고 각 FoxDataRequest 객체의 DatabaseName 속성에 null 이 아닌 연결 문자열의 이름을 지정합니다. 이렇게 하면 개별 쿼리가 각각 지정된 연결 문자열을 사용하여 수행됩니다.

다음 코드는 각 FoxDataRequest 객체마다 다른 데이터베이스 연결(AzurePostgreSQLOciPostgreSQL)을 사용하여 두 개의 쿼리를 수행하는 예제 코드입니다. FoxDataRequestCollection 클래스의 생성자에 연결 문자열 이름을 명시하지 않음으로써 DatabaseName 속성에 null 값을 지정하고, 각 FoxDataRequest 객체의 생성자에 연결 문자열 이름을 지정하였음을 주목하십시요.

1
2
3
4
5
6
7
8
FoxDataRequestCollection requests = new()   // DatabaseName 속성에 null 값을 지정
{
    new FoxDataRequest("orders.get_order_by_id", "AzurePostgreSQL") { Operation = FoxDataOperations.ExecuteDataSet },
    new FoxDataRequest("orders.get_details_by_id", "OciPostreSQL") { Operation = FoxDataOperations.ExecuteDataSet },
};
requests[0].Parameters["order_id"] = 1;
requests[1].Parameters["order_id"] = 1;
FoxDataResponseCollection responses = dataService.ExecuteMultiple(requests);

다음 로그는 ExecuteMultiple 메서드가 개별 연결을 사용하여 두 개의 쿼리를 수행할 때에 Fox Data Service 가 생성하는 로그입니다.

>> Data Service Start: ExecuteMultiple  Requests=2  UserId=  ClientMachine=NEOWORK2  ClientIP=  ClientMAC=
    Start Processing Request[0]
    & Using REQUEST scope dbaccess()
    & EXPLICITLY Open Database Connection...
    Before Invoke: DbAccess.ExecuteDataSet()  qid=orders.get_order_by_id  in-param=1
    After Invoke: DbAccess.ExecuteDataSet()  elpased = 9.5 msec
    & EXPLICITLY Close Database Connection...
    End Processing Request[0]  elapsed = 10.6 msec
    Start Processing Request[1]
    & Using REQUEST scope dbaccess()
    & EXPLICITLY Open Database Connection...
    Before Invoke: DbAccess.ExecuteDataSet()  qid=orders.get_details_by_id  in-param=1
    After Invoke: DbAccess.ExecuteDataSet()  elpased = 4.9 msec
    & EXPLICITLY Close Database Connection...
    End Processing Request[1]  elapsed = 5.3 msec
>> Data Service End: ExecuteMultiple  elapsed = 17.3 msec

위 로그에서 개별 FoxDataRequest 객체마다 별도의 FoxDbAccess 인스턴스가 생성되고 개별 데이터베이스 연결이 열렸다가 쿼리를 수행한 후 닫히는 것을 확인할 수 있습니다.

트랜잭션

Fox Data Service 는 FoxDataRequest 혹은 FoxDataRequestCollection 객체의 Transaction 속성에 적용하고자 하는 트랜잭션 모드를 FoxDataTransactions 열거 타입으로 지정하여 트랜잭션을 사용할 수 있습니다. 사용 가능한 트랜잭션 모드는 로컬 트랜잭션을 사용하는 LocalSystem.Transactions 네임스페이스의 TransactionScope 를 사용하는 Distributed, 트랜잭션을 사용하지 않는 None 세 가지이며 디폴트 값은 None 입니다.

로컬 트랜잭션

Transaction 속성 값을 FoxDataTransactions.Local 로 설정하면 Fox Data Service 는 로컬 트랜잭션을 사용하여 요청된 쿼리(들)을 수행합니다. 로컬 트랜잭션은 분산 트랜잭션에 비해 상대적으로 성능이 우수하므로 가능하다면 로컬 트랜잭션을 사용하는 것이 권장됩니다.

ExecuteMultiple 메서드를 사용하여 여러 쿼리를 배치로 수행하는 경우, 로컬 트랜잭션을 사용하기 위해서는 단일 데이터베이스 연결만을 사용해야 합니다. 따라서 FoxDataRequestCollection 객체의 DatabaseName 속성에 null 이 아닌 연결 문자열의 이름을 지정하거나 String.Empty 값을 사용하여 구성 설정에 지정된 디폴트 연결 문자열을 사용하도록 지정하십시오(Fox DB Access 의 연결 정보 선택 참조).

다음 코드는 구성 설정의 디폴트 연결 문자열(String.Empty)을 사용하여 2개의 INSERT 쿼리를 로컬 트랜잭션 하에 배치로 수행하는 예제 코드입니다. FoxDataRequestCollection 클래스의 생성자를 통해 DatabaseName 속성에 연결 문자열 이름을 명시하고 Transaction 속성에 FoxDataTransactions.Local 값을 설정하였음을 주목하십시요.

FoxDataRequestCollection requests = new(String.Empty)
{
    new FoxDataRequest("products.insert")
    {
        Parameters = { { "product_name", "Tx test data" }, { "unit_price", 999.99 } },
        Operation = FoxDataOperations.ExecuteNonQuery
    },
    new FoxDataRequest("testtable.insert")
    {
        Parameters = { { "col1", 999 }, { "col2", "Tx test data" } },
        Operation = FoxDataOperations.ExecuteNonQuery
    }
};
requests.Transaction = FoxDataTransactions.Local;
FoxDataServiceClient client = new("api/dataservice");
FoxDataResponseCollection responses = await client.ExecuteMultipleAsync(requests);

Note

위 예제 코드는 FoxDataServiceClient 클래스를 사용하여 원격 클라이언트가 Fox Web API 를 통해 Fox Data Service 를 호출하는 예제 코드입니다. 실제 코드는 Fox Data Service 트랜잭션 예제를 참고 하십시요.

분산 트랜잭션

Transaction 속성 값을 FoxDataTransactions.Distributed 로 설정하면 Fox Data Service 는 분산 트랜잭션을 사용하여 요청된 쿼리(들)을 수행합니다. 분산 트랜잭션은 System.Transactions 네임스페이스의 TransactionScope 를 사용하여 수행됩니다. 분산 트랜잭션은 여러 데이터베이스에 대한 쿼리들을 트랜잭션으로 묶어 수행하고자 할 때 매우 유용하게 사용할 수 있습니다. 하지만 분산 트랜잭션은 상대적으로 오버헤드를 가지며 Windows 플랫폼에 종속되어 Linux나 클라우드 환경에서 사용하기 어렵다는 단점을 고려하십시요.

Note

Fox Data Service 가 지원하는 분산 트랜잭션이 TransactionScope 를 사용하기 때문에 쿼리가 곧바로 분산 트랜잭션을 시작하지 않을 수도 있습니다. TransactionScope 는 일단 로컬 트랜잭션으로 트랜잭션을 수행하고 필요한 경우에만 분산 트랜잭션으로 승격(promote)합니다. 따라서 FoxDataTransactions.Distributed 값을 사용하더라도 실제로는 로컬 트랜잭션으로 수행될 수도 있습니다.

ExecuteMultiple 메서드를 사용하여 여러 데이터베이스에 대한 쿼리를 분산 트랜잭션을 묶어 처리하고자 하는 경우, Transaction 속성값을 FoxDataTransactions.Distributed 로 설정하고 FoxDataRequestCollection 객체의 DatabaseName 속성값은 null 로 설정하고 개별 FoxDataRequest 객체에 DatabaseName 속성값을 여러 데이터베이스 연결 문자열로 지정하면 됩니다. Fox Data Service 는 분산 트랜잭션을 시작하고 개별 FoxDataRequest 객체를 처리할 때마다 트랜잭션에 참여하여 데이터베이스 연결을 수행하고 쿼리를 수행할 것입니다. 그리고 이 모든 쿼리는 모두 성공하거나(commit) 모두 실패(abort) 할 것입니다.

다음 코드는 2개의 INSERT 쿼리를 분산 트랜잭션 하에 배치로 수행하는 예제 코드입니다. FoxDataRequestCollection 클래스의 생성자에 연결 문자열을 명시하지 않고(null 값을 사용) 개별 FoxDataRequest 객체의 생성자에 연결 문자열을 명시하였고 Transaction 속성에 FoxDataTransactions.Distributed 값을 설정하였음을 주목하십시요.

FoxDataRequestCollection requests = new()   // DatabaseName 속성에 null 값을 지정
{
    new FoxDataRequest("products.insert", "AzurePostgreSQL")
    {
        Parameters = { { "product_name", "Tx test data" }, { "unit_price", 999.99 } },
        Operation = FoxDataOperations.ExecuteNonQuery
    },
    new FoxDataRequest("testtable.insert", "OciPostreSQL")
    {
        Parameters = { { "col1", 999 }, { "col2", "Tx test data" } },
        Operation = FoxDataOperations.ExecuteNonQuery
    }
};
requests.Transaction = FoxDataTransactions.Distributed;
FoxDataServiceClient client = new("api/dataservice");
FoxDataResponseCollection responses = await client.ExecuteMultipleAsync(requests);

ExecuteMultiple 고려 사항

ExecuteMultiple 메서드를 통해 로컬 트랜잭션 하에서 여러 쿼리를 수행하고자 하는 경우, FoxDataRequestCollection 객체의 DatabaseName 속성에 null 이 아닌 연결 문자열의 이름을 지정하여 모든 쿼리가 동일한 데이터베이스 연결을 사용하도록 해야 합니다. ExecuteMultiple 메서드는 Transaction 속성값이 FoxDataTransactions.Local 이면서 DatabaseName 속성값이 null 인 경우, FoxDataServiceException 예외를 유발합니다.

트랜잭션 모드가 FoxDataTransactions.None 인 경우, ExecuteMultiple 메서드는 전체 쿼리들을 단일 트랜잭션으로 묶지 않으며 개별 쿼리별로 트랜잭션 사용 여부를 결정합니다. 즉, FoxDataRequest 객체의 Transaction 속성에 트랜잭션 모드를 지정하여 개별 쿼리마다 트랜잭션을 사용 여부를 지정할 수 있습니다.

예외 처리

Fox Data Service 가 데이터베이스 액세스 중에 발생하는 예외는 FoxDataServiceException 예외로 래핑되어 호출자에게 전달됩니다. FoxDataServiceException 예외는 InnerException 속성에 실제 예외를 포함합니다. 따라서 호출자는 FoxDataServiceException 예외를 캐치하여 InnerException 속성에서 실제 예외를 확인할 수 있습니다.

예외 처리에 대한 상세한 예제 코드는 다음을 참고 하십시요.

기본 예외 처리

Fox Data Service 가 실제 오류를 나타내는 예외 대신 FoxDataServiceException 예외를 사용하는 이유는 일관된 예외 처리 모델을 제공하기 위함입니다. 다음 코드 조각은 ASP.NET Core Web API 에서 Fox Data Service 를 호출하는 예제 코드입니다. 이 예제 코드에서는 FoxDataServiceException 예외를 캐치하여 InnerException 속성에서 실제 예외를 확인하고, 클라이언트에게 적절한 HTTP 상태 코드와 예외 정보를 반환합니다.

app.MapGet("/api/product/{id}", (string id) =>
{
    FoxDataService service = new();
    FoxDataRequest request = new("sample.error_query_id");
    request.Parameters.Add("product_id", id);
    try
    {
        FoxDataResponse response = service.ExecuteDataSet(request);
        return Results.Ok(response);
    }
    catch(FoxDataServiceException ex)
    {
        string errorType = ex.InnerException != null ? ex.InnerException.GetType().Name : ex.GetType().Name;
        return Results.Problem(detail: ex.Message, type: errorType);
    }
});

ExecuteMultiple 메서드나 SaveDataTable 메서드에서 발생하는 예외는 즉시 현재 작업을 중단하며 추가적인 쿼리를 수행하지 않고 예외를 클라이언트에게 전파하게 됩니다. 따라서 ExecuteMultiple 메서드나 SaveDataTable 메서드에서 예외가 발생하는 경우, 예외가 발생한 시점 이후에는 어떤 쿼리도 추가적으로 수행되지 않습니다. 예를 들어, ExecuteMultiple 메서드에서 5개의 쿼리를 수행하는 도중 3번째 쿼리에서 예외가 발생하면, 4번째와 5번째 쿼리는 수행되지 않고 예외가 클라이언트에게 전파됩니다.

서비스 오류 정보 객체

Fox Web API 와 같은 통신 서비스에서 Fox Data Service 를 호출할 때, FoxDataServiceException 예외는 통신 서비스의 예외 처리 모델과 호환되는 방식으로 변환되어 원격 클라이언트에게 전달될 수 있습니다. 예를 들어, ASP.NET Web API 에서 예외 필터를 통해 JSON 혹은 XML로 변환하여 예외 정보를 클라이언트에게 반환할 수 있습니다.

물론 Fox Web API 는 FoxDataServiceException 예외를 처리하는 예외 필터를 이미 제공하며 JSON 형태의 예외 정보를 원격 클라이언트에게 제공합니다. FoxServiceErrorInfo 클래스는 예외 정보를 담는 DTO(Data Transfer Object) 역할을 하며 FoxDataServiceException 예외에 포함된 예외 메시지, 호출 스택 등 정보는 이 DTO를 사용하여 JSON 으로 직렬화하여 클라이언트에게 반환합니다.

Fox Data Service 의 전형적인 사용 시나리오는 원격 클라이언트가 Fox Web API 를 통해 서비스를 호출하는 방식이므로 개발자는 FoxDataServiceException 예외를 직접 처리할 필요가 거의 없습니다. 대신 FoxServiceErrorInfo 객체에 포함된 정보를 더 많이 다루게 될 것입니다. 다음은 Fox Web API 가 FoxDataServiceException 예외를 처리하여 원격 클라이언트에게 반환하는 예제 JSON 입니다.

HTTP/1.1 500 Internal Server Error
Content-Type: application/problem+json
Date: Mon, 24 Aug 2026 06:58:52 GMT
Server: Kestrel
Transfer-Encoding: chunked

{
  "type":"FoxInvalidQueryException",
  "title":"An error occurred while processing your request.",
  "status":500,
  "detail":"'sample.foxml' 에서 쿼리 아이디 'error_query_id'을 찾을 수 없습니다."
}

FoxServiceErrorInfo 객체와 접근 방법에 대한 상세한 내용은 Fox Web API 클라이언트 문서를 참고 하십시요.

예외 전파 제어

Fox Data Service 는 쿼리 수행 중에 예외가 발생하는 경우, 기본적으로 해당 예외를 FoxDataServiceException 예외로 래핑하여 호출자에게 전파(propagate) 합니다. 하지만 FoxDataRequest 객체의 ThrowException 속성에 false 값이 지정된 경우 예외를 전파하는 대신 예외 정보(FoxServiceErrorInfo 객체)를 FoxDataResponse 객체의 ErrorInfo 속성에 포함하여 반환합니다. 다음 예제 코드는 원격 클라이언트가 Fox Web API 를 통해 Fox Data Service 를 호출할 때 ThrowException 속성에 false 값을 지정하여 예외를 전파하지 않고 예외 정보를 반환받는 예제 코드입니다.

1
2
3
4
5
6
7
8
9
FoxDataServiceClient client = new("/api/dataservice");
FoxDataRequest request = new("sample.error_query_id");
request.ThrowException = false;
FoxDataResponse response = client.ExecuteDataSet(request);
if (!response.Success)
{
    string errorMessage = response.ErrorInfo?.Message ?? "Unknown error";
    ......
}

이 경우, 호출자는 FoxDataResponse 객체의 Success 속성을 확인하여 쿼리의 성공여부를 먼저 파악하고 쿼리가 실패한 경우 ErrorInfo 속성에서 예외 정보를 확인할 수 있습니다.

ThrowException 속성은 ExecuteXXX 시리즈 메서드들에서 단일 쿼리를 수행하는 경우 뿐만 아니라 ExecuteMultiple 메서드에서 여러 쿼리를 배치로 수행하는 경우에도 적용됩니다. ExecuteMultiple 메서드에서는 FoxDataRequestCollection 객체의 ThrowException 속성에 false 값이 지정된 경우, 예외가 발생한 경우 FoxDataResponseCollection 객체에서 Success 속성을 false 를 설정하고 ErrorInfo 속성에서 예외를 발생한 FoxDataRequest 객체의 인덱스를 포함하는 예외 정보를 확인할 수 있습니다.

FoxDataServiceClient client = new("/api/dataservice");
FoxDataRequestCollection requests = CreateResponseCollection();
requests.ThrowException = false;
FoxDataResponseCollection responses = client.ExecuteMultiple(requests);
if (!responses.Success)
{
    int errorRequestIndex = responses.ErrorInfo.Index;
    string errorMessage = responses.ErrorInfo?.Message ?? "Unknown error";
    ......
}

위 예제 코드에서 responses 컬렉션은 2개의 FoxDataResponse 객체를 포함하며 첫 번째 FoxDataResponse 객체는 성공적으로 수행된 쿼리의 결과를 포함하고, 두 번째 FoxDataResponse 객체는 실패한 쿼리의 예외 정보를 포함합니다. 호출자는 responses.ErrorInfo.Index 속성을 확인하여 어떤 쿼리에서 예외가 발생했는지 확인할 수 있습니다.

Warning

컬렉션 전체에 적용되는 트랜잭션이 사용 중이고 오류가 발생되면 변경 사항은 모두 롤백됩니다. 따라서 ThrowException 속성이 false 로 설정되어 일부 성공한 쿼리의 결과가 FoxDataResponseCollection 객체에 반환되더라도 그 내용을 신뢰할 수 없음에 주의 하십시요.

Continue On Error

ExecuteMultiple 메서드는 여러 개의 쿼리를 배치로 수행하는 메서드이므로, 여러 쿼리 중 일부 쿼리가 실패하는 경우에도 나머지 쿼리를 계속 수행하도록 제어할 수 있습니다. 이를 위해 FoxDataRequestCollection 객체의 ContinueOnError 속성을 사용합니다. ThrowException 속성이 false 이고 ContinueOnError 속성에 true 값이 지정된 경우, 예외가 발생한 쿼리에 대한 예외 정보가 해당 쿼리의 FoxDataResponse 객체의 ErrorInfo 속성에 포함되어 반환되며, 나머지 쿼리들은 계속 수행됩니다.

FoxDataServiceClient client = new("/api/dataservice");
FoxDataRequestCollection requests = CreateResponseCollection();
requests.ThrowException = false;
requests.ContinueOnError = true;
FoxDataResponseCollection responses = client.ExecuteMultiple(requests);
foreach(FoxDataResponse response in responses)
{
    if (response.Success)
    {
        // ... 성공한 쿼리 결과 처리 (생략) ...
    }
    else
    {
        string errorMessage = response.ErrorInfo?.Message ?? "Unknown error";
        // ... 실패한 쿼리 결과 처리 (생략) ...
    }
}

ContinueOnError 속성이 true 로 지정되었더라도 FoxDataRequestCollection 컬렉션 전체에 적용되는 트랜잭션이 적용되면, 예외가 발생함에 따라 트랜잭션은 롤백되며 나머지 쿼리들은 수행되지 않습니다. 따라서 ContinueOnError 속성은 컬렉션 전체 적용되는 트랜잭션이 사용되지 않는 경우에만 의미가 있습니다.

한편, 각 FoxDataRequest 객체마다 개별 트랜잭션을 사용하는 경우, ContinueOnError 옵션에 따라서 일부 쿼리가 실패하더라도 나머지 쿼리들은 계속 수행될 수 있습니다.

로깅

Fox Data Service 는 코드를 작성하지 않고 데이터베이스 액세스를 수행하기 때문에 오류가 발생한 경우 추적 및 진단이 용이하지 않습니다. 따라서 Fox Data Service 는 수행 단계마다 상세한 로그를 남깁니다. 예를 들어 데이터베이스 연결이 언제 열렸으며 언제 닫혔는지, 로컬 혹은 분산 트랜잭션이 언제 시작되고 언제 커밋 혹은 롤백되었는지, 쿼리가 언제 실행되었으며 얼마나 시간이 소요되었는지 등에 대한 기록입니다. 이러한 로그는 Fox Data Service 가 데이터베이스 액세스를 수행하는 동안 발생하는 이벤트들을 추적하고 진단하는데 유용합니다.

서비스 로깅

Fox Data Service 는 FoxDataService 클래스의 LoggerName 속성 혹은 구성 설정의 "dataService:diagnostics:loggerName" 속성이 지정하는 로거에 로그를 기록합니다. LoggerName 속성의 디폴트 값은 NeoDEEX.ServiceModel.Data.FoxDataService 이지만 이 속성이 지정하는 로거가 등록되지 않은 경우 로그는 기록되지 않습니다. 다음은 FoxDataService 객체를 생성하고 서버 측 로깅을 활성화하는 예제입니다.

1
2
3
4
FoxDataService dataService = new()
{
    LoggerName = "MyLogger"
};

여러 차례 언급한바 있지만 개발자가 직접 FoxDataService 클래스의 인스턴스를 생성하여 Fox Data Service 를 호출하는 경우는 매우 적습니다. 대신 Fox Web API 와 같은 통신 서비스에서 Fox Data Service 를 사용하여 클라이언트의 요청을 처리하는 경우가 많습니다. 이러한 경우 ASP.NET Web API 와 같은 통신 서비스 앱의 구성 설정 파일에서 "dataService:diagnostics:loggerName" 속성을 설정하여 서버 측 로깅을 활성화할 수 있습니다.

1
2
3
4
5
6
7
{
  "dataService": {
    "diagnostics": {
        "loggerName": "MyLogger"
    }
  }
}

다음은 활성화된 서비스 로깅에 대한 예를 보여줍니다. 호출자 정보를 포함하여 호출되는 서비스 메서드(ExecuteDataSet), 쿼리 ID, 데이터베이스 연결 시작, 쿼리 수행 시간, 데이터베이스 연결 종료 등에 대한 로그가 기록됩니다.

1
2
3
4
5
6
I 2026-03-16 20:43:42.62316 [DataService] #00015:43361401#>> Data Service Start: ExecuteDataSet  Requests=1  UserId=  ClientMachine=NEOWORK2  ClientIP=192.168.0.46;172.29.96.1;172.20.96.1  ClientMAC=F8-9E-94-F1-3-79;0-15-5D-0-2D-0;0-15-5D-C6-82-FB
V 2026-03-16 20:43:42.64825 [DataService] #00015:43361401#    & EXPLICITLY Open Database Connection...
V 2026-03-16 20:43:42.76583 [DataService] #00015:43361401#    Before Invoke: DbAccess.ExecuteDataSet()  qid=orders.get_all_orders_with_details  in-param=0
V 2026-03-16 20:43:42.98382 [DataService] #00015:43361401#    After Invoke: DbAccess.ExecuteDataSet()  elpased = 216.8 msec
V 2026-03-16 20:43:42.98421 [DataService] #00015:43361401#    & EXPLICITLY Close Database Connection...
I 2026-03-16 20:43:42.98977 [DataService] #00015:43361401#>> Data Service End: ExecuteDataSet  elapsed = 370.3 msec

로그 ID

Fox Data Service 가 사용되면 다수의 클라이언트로부터 동시에 여러 요청이 들어오며 이들은 동시에 처리됩니다. 따라서 Fox Data Service 가 생성하는 로그는 여러 클라이언트 요청에 대한 로그가 섞여서 기록될 수 있습니다. 어떤 쿼리에 성능 문제나 오류가 발생한 경우 해당 쿼리와 관련된 로그를 식별하는 것이 중요합니다. 동시에 처리되는 여러 요청들을 처리하는 Fox Data Service 는 동시에 수 많은 로그 항목을 생성하기 때문에 로그 항목이 어떤 요청을 처리하면서 기록된 것인지 손쉽게 파악할 방법이 필요합니다.

Fox Data Service 에 대한 로그는 로그 ID 라는 식별자를 포함합니다. 로그 ID 는 # 문자로 구분된 두 개의 8자리 16진수 숫자로 구성됩니다. 예를 들어, 위 예시 로그에서 #00015:43361401# 이 부분이 로그 ID 입니다. 로그 ID 는 Fox Data Service 가 하나의 클라이언트 요청을 처리하는 동안 생성되는 모든 로그에 포함됩니다. 따라서 클라이언트 요청과 관련된 모든 로그를 쉽게 식별할 수 있습니다.

Warning

로그 ID 는 GUID 와 같은 고유 식별자가 아닙니다. 로그 ID 는 스레드 ID 와 FoxDataService 인스턴스 식별자 조합이기 때문에 특정 서버에서 일정 기간 내에서만 고유합니다. 따라서 로그 ID 를 긴 시간동안 보관된 로그에서 특정 클라이언트 요청과 관련된 로그를 식별하는데 사용하는 것은 적절하지 않습니다. 로그 ID 는 동시 호출이 발생하는 상황에서 하나의 요청을 처리하는 로그를 구별하는 용도로 사용하는 것이 적절합니다.

동시에 여러 클라이언트가 Fox Data Service 에 요청을 보내는 경우, 각 클라이언트 요청에 대해 고유한 로그 ID 가 생성되어 각 요청과 관련된 로그를 구분할 수 있습니다. 또한 하나의 클라이언트가 여러 개의 요청을 보내는 경우에도 각 요청에 대해 고유한 로그 ID 가 생성됩니다. 로그 ID 는 Fox Data Service 가 클라이언트 요청을 처리하는 동안 생성되는 모든 로그에 포함되므로, 클라이언트 요청과 관련된 모든 로그를 쉽게 식별할 수 있습니다.

로그 ID 는 클라이언트의 요청에 의해 클라이언트에게 반환될 수도 있습니다. 클라이언트는 FoxDataRequest 객체의 Diagnostics 속성에 FoxDataRequestDiagnostics.LogId 플래그를 설정하여 클라이언트 요청과 관련된 로그 ID 를 FoxDataResponse 객체의 LogId 속성에 포함하여 반환하도록 할 수 있습니다. 클라이언트는 반환된 로그 ID 를 사용하여 서버 측 로그에서 해당 클라이언트 요청과 관련된 로그를 쉽게 식별할 수 있습니다.

다음 코드는 Fox Web API 클라이언트가 Fox Data Service 를 호출할 때 FoxDataRequest 객체의 Diagnostics 속성에 FoxDataRequestDiagnostics.LogId 플래그를 설정하여 클라이언트 요청과 관련된 로그 ID 를 FoxDataResponse 객체의 LogId 속성에 포함하여 반환하도록 하는 예제 코드입니다.

1
2
3
4
5
FoxDataServiceClient client = new("/api/dataservice");
FoxDataRequest request = new("sample.get_all_products");
request.Diagnostics = diagnostics.Value;
FoxDataResponse response = client.ExecuteDataSet(request);
Console.WriteLine($"Log ID: {response.LogId}");

Warning

서비스 로그, 로그 ID, 성능 정보, DB 프로파일 등과 같은 서버 측 정보는 민감한 정보가 될 수 있으므로 Web API 설정에서 FoxWebApiServerConfig.ReturnServerInfo 속성이 true 가 아닌 경우에는 Web API 수준에서 필터링되어 JSON 으로 직렬화되지 않아, 클라이언트에게 반환되지 않습니다.

1
2
3
4
5
{
  "webApiServer": {
    "returnServerInfo": true
  }
}

ExecuteMultiple 메서드에서 여러 쿼리를 수행하는 경우, 각 쿼리마다 개별 로그 ID 가 생성되지 않고 전체 요청을 처리하는 것에 대해 하나의 로그 ID 가 생성됩니다. 따라서 ExecuteMultiple 메서드에서 여러 쿼리를 수행하는 경우, FoxDataRequestCollection 객체의 Diagnostics 속성을 통해 요청을 해야 하며 FoxDataResponseCollection 객체의 LogId 속성에 로그 ID 가 포함되어 반환됩니다. 컬렉션에 포함된 각 FoxDataResponse 객체의 LogId 속성은 로그 ID 를 포함하지 않고 null 값을 반환합니다.

요청 시 로깅

서비스 로그는 서버 측에서 로거를 사용하여 기록하는 로그 입니다. 반면 "요청 시 로깅"은 클라이언트가 로그를 요청하면 쿼리를 수행하면서 발생하는 로그를 클라이언트에게 반환하는 기능입니다. 요청 시 로깅을 활성화하려면, FoxDataRequest 객체의 Diagnostics 속성에 FoxDataRequestDiagnostics.ServiceLog 플래그를 설정합니다. 요청 시 로깅이 활성화된 경우, 쿼리를 수행하면서 발생하는 로그가 FoxDataResponse 객체의 ServiceLog 속성(string[] 타입)에 포함되어 반환됩니다.

1
2
3
4
5
6
FoxDataRequest dataRequest = new("your query id")
{
    Diagnostics = FoxDataRequestDiagnostics.ServiceLog
};
FoxDataResponse dataResponse = dataService.ExecuteDataSet(dataRequest);
string[] serviceLog = dataResponse.ServiceLog;

요청 시 로깅은 FoxDataService 클래스의 EnableDiagnostics 속성이 true로 설정된 경우에 작동하며 서비스 로그와 무관하게 작동합니다. 동시 사용자가 많은 서비스 환경에서 서버에 부하를 주지 않고 특정 요청에 대해서만 로그를 추적할 수 있기 때문에 트러블 슈팅이나 디버깅에 크게 도움이 될 수 있습니다.

Warning

서비스 로그 정보 역시 민감한 정보가 포함될 수 있으므로 Web API 설정에서 ReturnServerInfo 속성이 true 가 아닌 경우에는 Web API 수준에서 필터링되어 JSON 으로 직렬화되지 않아, 클라이언트에게 반환되지 않습니다.

로그 ID 기능과 동일하게 ExecuteMultiple 메서드 호출에 대해 요청 시 로깅 기능을 활성화 하려면 FoxDataRequestCollection 객체의 Diagnostics 속성에 FoxDataRequestDiagnostics.ServiceLog 플래그를 설정해야 합니다. ExecuteMultiple 메서드를 수행하면서 생성되는 로그 항목은 FoxDataResponseCollection 객체의 ServiceLog 속성에 포함되어 반환되며, 컬렉션에 포함된 각 FoxDataResponse 객체의 ServiceLog 속성에는 로그 항목이 포함되지 않습니다.

성능 측정

Fox Data Service 는 쿼리를 수행하면서 주요 처리 과정에 대한 성능 측정을 수행합니다. 이렇게 측정된 성능 정보는 로그를 통해 표시됩니다. 예를 들어, ExecuteMultiple 메서드가 여러 쿼리를 수행하는 동안 개별 SQL 에 소요된 시간, 개별 쿼리에 대해 소요된 총 시간, 그리고 컬렉션 내의 전체 쿼리들을 모두 수행하는데 소요되는 시간을 모두 측정하여 로그에 표시합니다.

 >> Data Service Start: ExecuteMultiple  Requests=2  UserId=  ClientMachine=  ClientIP=  ClientMAC=
     Start Processing Request[0]
     & Using REQUEST scope dbaccess()
     & EXPLICITLY Open Database Connection...
     Before Invoke: DbAccess.ExecuteDataSet()  qid=sample.get_all_products  in-param=0
     After Invoke: DbAccess.ExecuteDataSet()  elpased = 4.2 msec
     & EXPLICITLY Close Database Connection...
     End Processing Request[0]  elapsed = 4.7 msec
     Start Processing Request[1]
     & Using REQUEST scope dbaccess()
     & EXPLICITLY Open Database Connection...
     Before Invoke: DbAccess.ExecuteDataSet()  qid=sample.get_product_by_id  in-param=1
     After Invoke: DbAccess.ExecuteDataSet()  elpased = 8.6 msec
     & EXPLICITLY Close Database Connection...
     End Processing Request[1]  elapsed = 8.7 msec
 >> Data Service End: ExecuteMultiple  elapsed = 14.0 msec

로그 뿐만 아니라 매 호출마다 반환하는 FoxDataResponse 객체의 ElapsedMilliseconds 속성에 쿼리 수행에 소요된 시간을 밀리초 단위로 포함하여 반환합니다. 서비스 수행 시간은 EnableDiagnostics 속성값이나 EnablePerfLog 속성값과 무관하게 항상 측정되며 항상 클라이언트에게 반환됩니다.

1
2
3
FoxDataRequest dataRequest = new("your query id");
FoxDataResponse dataResponse = dataService.ExecuteDataSet(dataRequest);
double elapsed = dataResponse.ElapsedMilliseconds;

ExecuteMultiple 메서드는 FoxDataResponseCollection 객체의 ElapsedMilliseconds 속성에 모든 쿼리를 수행하는데 소요되는 시간을 반환하며, 컬렉션에 포함된 각 FoxDataResponse 객체의 ElapsedMilliseconds 속성에는 해당 쿼리를 수행하는데 소요된 시간이 반환됩니다.

성능 문맥 로그

단순한 로그 메시지 뿐만 아니라 성능 문맥 기능(Fox Performance Context)과 연계하여 쿼리 수행에 대한 다양한 정보를 포함하는 성능 로그를 기록할 수도 있습니다. 성능 로그는 EnablePerfLog 속성이 true로 설정된 경우 활성화되며 측정된 성능 문맥 정보는 PerfLoggerName 속성이 지정하는 로거에 기록됩니다. 다음은 구성 설정을 통해 EnablePerfLog 속성을 true로 설정하고 성능 로그를 기록하는 로거 이름을 지정하는 예제입니다.

{
  "dataService": {
    "perfLog": {
      "enable": true,
      "loggerName": "PerfLogger"
    }
  },
  "logging": {
    "PerfLogger": {
      "providerType": "NeoDEEX.Diagnostics.Loggers.FoxTextFileLoggerProvider"
    }
  }
}

다음은 앞서 ExecuteMultiple 메서드 호출 예제에서 EnablePerfLog 속성을 true로 설정하여 성능 로그를 활성화한 경우의 예시 로그입니다. ExecuteMultiple 메서드가 전체적으로 14.05 밀리초(msec)가 소요되었으며, 이 메서드 내에서 호출된 ExecuteDataSet 메서드들의 수행 시간과 각 쿼리 수행에 대한 Fox Query 의 수행시간도 포함된 로그 입니다.

1
2
3
4
5
6
I 2026-08-27 17:40:23.56622 [PerfLogger] Performance Activity [NEOWORK2:16512:FoxDataService;DataAccessLayer] elapsed=14.05 time=17:40:23:5521 id=a2198451-6842-4641-8973-7fcf6ed7ae28
    ExecuteMultiple inclusive=14.05 exclusive=0.68 time=17:40:23:5521 id=3 parent=-1
        ExecuteDataSet inclusive=4.69 exclusive=0.51 time=17:40:23:5526 id=4 parent=3
            FoxQuery inclusive=4.17 exclusive=4.17 time=17:40:23:5530 id=5 parent=4
        ExecuteDataSet inclusive=8.68 exclusive=0.12 time=17:40:23:5573 id=6 parent=3
            FoxQuery inclusive=8.56 exclusive=8.56 time=17:40:23:5574 id=7 parent=6

요청 시 성능 정보

Fox Data Service 는 요청 시 로깅(FoxDataRequestDiagnostics.ServiceLog) 기능과 유사하게 클라이언트 요청에 따라 수행하는 쿼리 수행에 대한 성능을 측정하여 반환하는 기능도 제공합니다. FoxDataRequest 객체의 Diagnostics 속성에 FoxDataRequestDiagnostics.PerformanceInfo 플래그를 설정하여 서비스가 쿼리를 수행하는데 소요되는 성능 문맥 정보를 반환하도록 요청할 수 있습니다. 요청이 활성화된 경우, 쿼리를 수행하면서 측정된 성능 정보가 FoxDataResponse 객체의 PerformanceInfo 속성에 포함되어 반환됩니다.

PerformanceInfo 속성은 FoxPerformanceActivityInfo 객체로, 쿼리 수행에 대한 성능 문맥 정보를 계층 구조로 포함하고 있습니다. 따라서 쿼리 수행에 대한 상세한 성능 정보를 확인할 수 있습니다. 앞서 살펴보았던 성능 로그는 성능 정보를 나타내는 FoxPerformanceActivityInfo 객체를 문자열로 표시한(ToString() 메서드) 결과입니다.

다음 코드는 Fox Web API 클라이언트가 FoxDataRequestCollection 객체의 Diagnostics 속성에 FoxDataRequestDiagnostics.PerformanceInfo 플래그를 설정하여 Fox Data Service 에게 ExecuteMultiple 메서드를 수행하면서 성능 정보를 반환하도록 요청하는 예제 입니다.

1
2
3
4
5
6
7
8
FoxDataServiceClient client = new("/api/dataservice");
FoxDataRequest request1 = new("sample.get_all_products") { Operation = FoxDataOperations.ExecuteDataSet };
FoxDataRequest request2 = new("sample.get_product_by_id") { Operation = FoxDataOperations.ExecuteDataSet };
request2.Parameters.Add("product_id", "P001");
FoxDataRequestCollection requests = [request1, request2];
requests.Diagnostics = FoxDataRequestDiagnostics.PerformanceInfo;
FoxDataResponseCollection responses = client.ExecuteMultiple(requests);
Console.WriteLine(responses.PerformanceInfo.ToString());

위 호출은 다음과 같은 성능 정보를 출력하게 됩니다. 이 결과는 성능 로그와 동일한 내용이며 Fox Data Service 클라이언트가 서비스 측에서 생성되는 성능 로그와 동일한 성능 정보를 반환받는 것을 확인할 수 있습니다.

1
2
3
4
5
6
7
Performance Activity [NEOWORK2:29796:FoxDataService;DataAccessLayer] elapsed=8.97 time=20:30:28:1227
id=f1b94e4f-4e7f-4e03-af0e-58fe9418e0b1
    ExecuteMultiple inclusive=8.97 exclusive=0.22 time=20:30:28:1227 id=6 parent=-1
        ExecuteDataSet inclusive=4.76 exclusive=0.55 time=20:30:28:1228 id=7 parent=6
            FoxQuery inclusive=4.21 exclusive=4.21 time=20:30:28:1230 id=8 parent=7
        ExecuteDataSet inclusive=3.98 exclusive=0.20 time=20:30:28:1276 id=9 parent=6
            FoxQuery inclusive=3.78 exclusive=3.78 time=20:30:28:1277 id=10 parent=9

성능 로그에 쌓이는 수많은 로그 항목들 중에서 성능 정보를 찾는 것보다 클라이언트에게 반환된 성능 정보를 통해 방금 호출한 쿼리의 성능 정보를 바로 확인할 수 있으므로, 성능 로그를 통해 성능을 확인하는 것보다 훨씬 편리합니다. 또한 성능 로그는 서버 측에서만 확인할 수 있지만, 요청 시 성능 정보는 클라이언트가 직접 확인할 수 있습니다.

Warning

요청 시 성능 정보는 성능 정보를 직렬화해야 하며 응답의 크기를 증가시키므로 네트워크 대역폭에 좋지 않은 영향을 줄 수 있습니다. 따라서 일반적인 상황에서는 이 기능을 사용하지 않는 것이 좋으며 개발 단계 혹은 성능 문제를 진단하는 상황에서만 이 기능을 사용하는 것이 좋습니다.

요청 시 DB 프로파일 정보

요청 시 성능 정보와 유사하게 Diagnostics 속성에 FoxDataRequestDiagnostics.DbProfileInfo 플래그를 설정하여 서비스가 쿼리를 수행하는 동안 수집된 Fox Query 의 DB 프로파일 정보를 반환하도록 요청할 수도 있습니다. 요청이 활성화된 경우, 쿼리를 수행하면서 수집된 DB 프로파일 정보(FoxDbProfileInfo 객체)가 FoxDataResponse 객체의 DbProfileInfo 속성에 포함되어 반환됩니다.

다음 예제는 Razor 페이지에서 ExecuteDataSet 메서드를 호출하여 쿼리를 수행하는 예제 코드입니다. Diagnostics 속성에 성능 로그 플래그와 DB 프로파일 플래그를 설정하여 성능 정보를 요청합니다. 반환된 성능 정보를 HTML 페이지에 렌더링하는 예시 코드입니다.

@{
    FoxDataRequest dataRequest = new("orders.get_all_orders_with_details")
    {
        Diagnostics = FoxDataRequestDiagnostics.PerformanceInfo | FoxDataRequestDiagnostics.DbProfileInfo
    };
    FoxDataResponse dataResponse = dataService.ExecuteDataSet(dataRequest);
}
...... HTML 렌더링 (생략) ......
<pre><code class="plaintext">@dataResponse.PerformanceInfo.ToString()</code></pre>
...... 
<pre><code class="plaintext">@dataResponse.DbProfileInfo.ToString()</code></pre>
...... HTML 렌더링 (생략) ......

성능 문맥 정보와 DB 프로파일 정보가 포함된 요청 시 성능 측정 예시

Warning

표시된 DB 프로파일 정보에는 쿼리에 사용된 SQL 문장과 .foxml 파일의 파일 시스템 내의 위치가 포함되어 있습니다. 이러한 정보는 민감한 정보가 될 수 있으므로 FoxDataService 객체의 EnableDetailedDbProfile 속성을 true로 설정하거나 구성 설정에서 "dataService:diagnostics:detailedDbProfile" 값을 true로 설정하여 명시적으로 활성화하지 않는 한, 민감한 서버 정보는 필터링 되어 반환되지 않습니다.

1
2
3
4
5
6
7
{
  "dataService": {
    "diagnostics": {
        "detailedDbProfile": true
    }
  }
}

다른 진단 플래그와 달리 DB 프로파일 정보는 쿼리 마다 그 정보를 읽어야 하므로 ExecuteMultiple 메서드를 호출하더라도 개별 FoxDataRequest 객체의 Diagnostics 속성에 FoxDataRequestDiagnostics.DbProfileInfo 플래그를 설정해야 하며, 반환된 DB 프로파일 정보는 FoxDataResponse 객체의 DbProfileInfo 속성에 포함되어 반환됩니다.

Note

DB 프로파일 정보는 쿼리 수행마다 측정이 되고 정보가 생성됩니다. 하지만 SaveDataTable 메서드는 여러 개의 Fox Query 를 수행하지만 하나의 FoxDataResponse 객체만 반환되므로, SaveDataTable 메서드 호출 시에는 DB 프로파일 정보가 반환되지 않습니다. 따라서 SaveDataTable 메서드 호출 시에는 서버 측 DB 프로파일 정보 로그를 통해 DB 프로파일 정보를 확인해야 합니다.

기타 기능

강제 트랜잭션 롤백

트랜잭션이 정상적으로 작동하는지 확인하는 가장 확실한 방법은 정상적으로 롤백이 수행되는가 확인하는 것입니다. 하지만 강제로 오류를 유발하는 SQL 문장을 사용하지 않는다면 트랜잭션이 정상적으로 롤백되는지 확인하기 어렵습니다. Fox Data Service 는 이러한 문제를 해결하기 위해 강제 트랜잭션 롤백 기능을 제공합니다.

FoxDataRequest 객체의 Diagnostics 속성에 FoxDataRequestDiagnostics.ForceRollback 플래그를 설정하면 쿼리가 성공적으로 수행되었더라도 강제적으로 롤백을 수행합니다. 특히 이 기능은 SaveDataTable 이나 ExecuteMultiple 메서드를 호출하여 데이터를 변경하고 트랜잭션을 강제 롤백하여 트랜잭션이 정상적으로 작동하는지 확인하는 테스트 용도로 매우 유용합니다.

Warning

강제 트랜잭션 롤백 기능은 쿼리가 성공적으로 수행되었더라도 강제적으로 롤백을 수행하므로, 이 기능을 활성화한 상태에서 데이터를 변경하는 쿼리를 수행하면 데이터베이스에 변경 사항이 반영되지 않습니다. 따라서 이 기능은 테스트 용도로만 사용해야 하며, 실제 운영 환경에서는 사용하지 않도록 주의해야 합니다.

로깅 억제 플래그

Fox Data Service 는 쿼리를 수행하면서 발생하는 로그를 기록하며 DB 프로파일 정보와 성능 정보를 수집합니다. 하지만 모든 요청에 대해 성능 정보와 DB 프로파일 정보를 수집하는 것이 필요한 것은 아닙니다. 예를 들어, 간단히 사용자 이름만 조회하는 쿼리나 다국어를 위해 문자열을 조회하는 쿼리는 굳이 성능 정보와 DB 프로파일 정보를 수집할 필요가 없을 수 있습니다.

너무 많은 성능 정보, DB 프로파일 정보가 기록되지 않도록 이들 정보가 필요하지 않은 쿼리에 대해 FoxDataRequest 객체의 Diagnostics 속성에 SuppressPerfLogWrite 플래그나 SuppressDbProfileWrite 플래그를 설정하면 성능 정보, DB 프로파일 정보가 로그에 기록되지 않도록 억제할 수 있습니다.

Note

Fox Data Service 가 생성하는 서비스 측 로그는 억제되지 않습니다. 억제 플래그는 서버측에서 로그가 기록되는 것을 억제할 뿐입니다. 따라서 억제 플래그를 설정하더라도 서비스 로그는 기록되며, 요청 시 로깅, 요청 시 성능 정보, 요청 시 DB 프로파일 기능을 사용하여 필요한 정보를 획득하는 것도 가능합니다.

Summary

Fox Data Service 는 매우 다양한 기능을 제공합니다. ExecuteMultiple 메서드를 통해 여러 쿼리를 배치로 수행할 수 있으며, 트랜잭션, 고급 예외 처리, 로깅, 성능 측정등 다양한 기능을 제공합니다. 이러한 기능들을 적절히 활용하면 데이터베이스 액세스를 보다 효과적으로 처리할 수 있고, 이 과정에서 발생하는 다양한 문제를 효과적으로 진단하고 해결할 수 있습니다.