데이터 서비스 컨텍스트 관리(WCF Data Services)
DataServiceContext 클래스는 지정한 데이터 서비스에 대해 지원되는 작업을 캡슐화합니다. OData 서비스는 상태 비저장 특성을 갖지만 컨텍스트는 그렇지 않습니다. 따라서 변경 관리 등의 기능을 지원하기 위해 DataServiceContext 클래스를 사용하여 데이터 서비스와의 상호 작용 간에 클라이언트에서 상태를 유지할 수 있습니다. 또한 이 클래스는 ID를 관리하고 변경 내용을 추적합니다.
병합 옵션 및 ID 확인
DataServiceQuery<TElement>가 실행되면 응답 피드의 엔터티가 개체로 구체화됩니다. 자세한 내용은 개체 구체화(WCF Data Services)를 참조하십시오. 응답 메시지의 항목이 개체로 구체화되는 방법은 ID 확인에 따라 수행되며 쿼리가 실행된 병합 옵션에 따라 달라집니다. 여러 쿼리 또는 로드 요청이 단일 DataServiceContext의 범위에서 실행되는 경우 WCF Data Services 클라이언트는 특정 키 값이 있는 개체의 단일 인스턴스만 추적합니다. ID 확인을 수행하는 데 사용되는 이 키는 엔터티를 고유하게 식별합니다.
기본적으로 클라이언트는 응답 피드의 항목을 DataServiceContext에 의해 추적되지 않는 엔터티의 개체로만 구체화합니다. 즉, 캐시에 이미 있는 개체의 변경 내용이 덮어쓰여지지 않습니다. 쿼리 및 로드 작업에 MergeOption 값을 지정하여 이 동작을 제어합니다. 이 옵션은 DataServiceContext에서 MergeOption 속성을 설정하여 지정합니다. 기본 병합 옵션 값은 AppendOnly입니다. 이 경우 추적되지 않는 엔터티의 개체만 구체화되므로 기존 개체는 덮어쓰여지지 않습니다. 클라이언트의 개체에 대한 변경 내용이 데이터 서비스의 업데이트에 의해 덮어쓰여지지 않도록 하는 다른 방법은 PreserveChanges를 지정하는 것입니다. OverwriteChanges를 지정하면 클라이언트의 개체 값은 해당 개체가 이미 변경된 경우에도 응답 피드에 있는 항목의 최신 값으로 대체됩니다. NoTracking 병합 옵션을 사용하는 경우 DataServiceContext는 클라이언트 개체의 변경 내용을 데이터 서비스에 보낼 수 없습니다. 이 옵션을 사용하면 변경 내용이 항상 데이터 서비스의 값으로 덮어쓰여집니다.
동시성 관리
OData는 데이터 서비스에서 업데이트 충돌을 감지할 수 있도록 하는 낙관적 동시성을 지원합니다. 데이터 서비스에서 동시성 토큰을 사용하여 엔터티의 변경 내용을 확인하는 방식으로 데이터 서비스 공급자를 구성할 수 있습니다. 이 토큰에는 리소스 변경 여부를 확인하기 위해 데이터 서비스에서 유효성이 검사되는 엔터티 형식의 속성이 하나 이상 포함됩니다. 데이터 서비스로의 요청과 데이터 서비스에서의 응답에 있는 eTag 헤더에 포함된 동시성 토큰은 WCF Data Services 클라이언트에서 자동으로 관리됩니다. 자세한 내용은 데이터 서비스 업데이트(WCF Data Services)를 참조하십시오.
DataServiceContext는 AddObject, UpdateObject 및 DeleteObject를 사용하거나 DataServiceCollection<T>에 의해 수동으로 보고된 개체의 변경 내용을 추적합니다. SaveChanges 메서드가 호출되면 클라이언트가 변경 내용을 데이터 서비스에 보냅니다. SaveChanges는 클라이언트의 데이터 변경 내용이 데이터 서비스의 변경 내용과 충돌하는 경우 실패할 수 있습니다. 이러한 경우에는 엔터티 리소스에 대한 쿼리를 다시 실행하여 업데이트 데이터를 받아야 합니다. 데이터 서비스의 변경 내용을 덮어쓰려면 PreserveChanges 병합 옵션을 사용하여 쿼리를 실행합니다. SaveChanges를 다시 호출하면 데이터 서비스의 해당 리소스에 다른 변경이 이미 수행되지 않은 경우 클라이언트에 유지된 변경 내용이 데이터 서비스에 유지됩니다.
변경 내용 저장
변경 내용이 DataServiceContext 인스턴스에서 추적되기는 하지만 서버로 즉시 전송되지는 않습니다. 지정한 작업에 대해 필요한 변경을 모두 마치면 SaveChanges를 호출하여 모든 변경 내용을 데이터 서비스에 전송합니다. SaveChanges 작업이 완료된 후에는 DataServiceResponse 개체가 반환됩니다. DataServiceResponse 개체는 유지되거나 시도된 변경 내용을 나타내는 EntityDescriptor 또는 LinkDescriptor 인스턴스의 시퀀스가 차례로 포함되는 OperationResponse 개체의 시퀀스를 포함합니다. 데이터 서비스에서 엔터티를 만들거나 수정하면 EntityDescriptor에는 위 예제에서 생성된 ProductID 값과 같은 서버에서 생성된 속성 값을 포함하여 업데이트된 엔터티에 대한 참조가 포함됩니다. 클라이언트 라이브러리는 .NET Framework 개체를 이러한 새 값으로 자동으로 업데이트합니다.
성공적인 삽입 및 업데이트 작업을 위해 해당 작업과 연결된 EntityDescriptor 또는 LinkDescriptor 개체의 상태 속성은 Unchanged로 설정되고 새 값은 OverwriteChanges를 통해 병합됩니다.
데이터 서비스에서 삽입, 업데이트 또는 삭제 작업이 실패하면 엔터티 상태는 SaveChanges가 호출되기 전과 동일하게 유지되며, OperationResponse의 Error 속성은 오류 정보가 포함된 DataServiceRequestException으로 설정됩니다. 자세한 내용은 데이터 서비스 업데이트(WCF Data Services)를 참조하십시오.
요청 관리
OData 프로토콜은 데이터 서비스에 대한 요청 및 데이터 서비스로부터의 응답 동작에 유연성을 제공합니다. 클라이언트 라이브러리를 사용하면 응용 프로그램이 데이터 서비스와 상호 작용하는 방식을 제어하여 이 유연성을 활용할 수 있습니다.
변경 작업에 대한 Prefer 헤더 설정
기본적으로 메시지 페이로드는 POST 요청에 대한 응답으로만 반환되어 새 엔터티를 만듭니다. 이 경우 새 엔터티는 페이로드에 반환됩니다. 즉, 개체에 대한 업데이트가 수행되면 업데이트된 엔터티가 페이로드 또는 응답 메시지에 반환되지 않습니다. 그러나 OData 프로토콜은 클라이언트가 선호 헤드를 사용하여 이 기본 동작으로부터의 변경을 요청할 수 있다고 표현합니다. POST, PUT, PATCH 또는 MERGE 요청의 Prefer 헤더는 AddAndUpdateResponsePreference 속성에 설정된 DataServiceResponsePreference 값에 기초한 DataServiceContext에 의해 생성됩니다. 다음 표는 Prefer 헤더 옵션 및 관련된 응답 동작을 보여 줍니다.
Prefer 헤더 값 |
응답 동작 |
|
---|---|---|
요청에 포함되어 있지 않습니다. 이는 기본 동작입니다. |
응답 페이로드는 POST 요청에 대해서만 반환되며 PUT, PATCH 및 MERGE 요청에 반환되지 않습니다. |
|
return-content |
응답 페이로드가 모든 변경 요청에 대해 반환됩니다. |
|
return-no-content |
어떤 요청에 대해서도 반환된 응답 페이로드가 없습니다. POST 요청에 대한 데이터 서비스에는 응답의 DataServiceId 헤더도 포함되어 있습니다. 이 헤더는 새로 생성된 엔터티의 키 값을 전달하는 데 사용됩니다. |
참고
데이터 서비스가 Prefer 헤더를 지원하는 OData 프로토콜 버전을 지원하는 경우에도 데이터 서비스에서 이러한 종류의 요청 처리 기본 설정을 무시할 수 있습니다.
업데이트를 위한 HTTP 메서드 설정
기본적으로 .NET Framework 클라이언트 라이브러리는 기존 엔터티에 대한 업데이트를 MERGE 요청으로 보냅니다. OData에서 MERGE 요청은 엔터티의 선택된 속성을 업데이트합니다. 하지만 클라이언트는 변경되지 않은 속성을 비롯하여 MERGE 요청에 항상 모든 속성을 포함합니다. 또한 OData 프로토콜은 PUT 및 PATCH 요청을 보내 엔터티를 업데이트하도록 지원합니다. PUT 요청에서 기존 엔터티는 클라이언트의 속성 값이 있는 엔터티의 새로운 인스턴스로 바뀝니다. PATCH 요청은 MERGE 요청과 동일한 방식으로 처리됩니다. 하지만 PATCH가 표준 HTTP 동작인 반면 MERGE는 OData에 의해 정의됩니다. 이 업데이트 동작은 SaveChanges(SaveChangesOptions)를 호출할 때의 옵션으로 PUT 요청을 사용하기 위한 ReplaceOnUpdate 값 또는 PATCH 요청을 사용하기 위한 PatchOnUpdate 값을 제공하여 지정됩니다.
참고
클라이언트가 엔터티의 모든 속성에 대해 인식하지 못하는 경우 PUT 요청은 MERGE 또는 PATCH 요청과 다르게 동작합니다.엔터티 유형을 클라이언트의 새로운 유형으로 프로젝션할 때 이런 상황이 발생할 수 있습니다.또한 새로운 속성이 서비스 데이터 모델의 엔터티에 추가되고 DataServiceContext의 IgnoreMissingProperties 속성이 true로 설정되어 이러한 클라이언트 매핑 오류를 무시하는 경우에도 이런 상황이 발생할 수 있습니다. 이런 경우 PUT 요청이 클라이언트에 알려지지 않은 모든 속성을 기본값으로 다시 설정합니다.
POST 터널링
기본적으로 클라이언트 라이브러리는 POST, GET, PUT/MERGE/PATCH 및 DELETE의 해당 HTTP 메서드를 사용하여 OData 서비스에 대한 생성, 읽기, 업데이트 및 삭제 요청을 보냅니다. 이는 REST(Representational State Transfer) 기본 원칙을 준수합니다. 그러나, 모든 웹 서버 구현이 전체 HTTP 메서드 집합을 지원하는 것은 아닙니다. 경우에 따라 지원되는 메서드가 GET 및 POST로만 제한될 수 있습니다. 이는 방화벽 같은 매개자가 특정 메서드를 사용하여 요청을 차단할 경우 발생할 수 있습니다. GET 및 POST 메서드가 가장 많이 지원되는 메서드이기 때문에 OData는 POST 요청을 사용하여 지원되지 않는 모든 HTTP 메서드를 실행하는 방법을 지정합니다. 메서드 터널링 또는 POST 터널링으로 알려진 이 방법을 사용하면 클라이언트가 사용자 지정 X-HTTP-Method 헤더에 지정된 실제 메서드를 사용하여 POST 요청을 보낼 수 있습니다. 요청에 대해 POST 터널링을 사용하도록 설정하려면 DataServiceContext 인스턴스의 UsePostTunneling 속성을 true로 설정합니다.
엔터티 집합의 기본 URI 확인
기본적으로 클라이언트는 컬렉션이라고도 하는 모든 엔터티 집합이 같은 기본 URI를 공유하는 것을 가정합니다. 이 기본 URI는 DataServiceContext의 BaseUri 속성에 의해 정의됩니다. 하지만 OData 프로토콜을 사용하면 데이터 서비스에서 다른 기본 URI가 있는 피드로 엔터티 집합을 노출할 수 있습니다. 다른 기본 URI를 사용하여 엔터티 집합을 처리할 수 있도록 클라이언트에서는 다양한 엔터티 집합의 기본 URI를 확인하는 데 사용할 수 있는 DataServiceContext를 사용하여 대리자를 등록할 수 있습니다. 이 대리자는 문자열(엔터티 집합 이름)을 사용하고 Uri(지정된 엔터티 집합에 대한 기본 URI)를 반환하는 메서드입니다. 이 확인자는 ResolveEntitySet 속성에 대한 할당에 의해 DataServiceContext와 함께 등록됩니다. 확인자 구현을 예를 들면, 컨텍스트가 만들어질 때 데이터 서비스 루트에서 반환된 컬렉션에 대한 정보를 읽고 사전의 각 컬렉션에 대한 기본 URI 값을 저장하는 경우입니다. 그런 다음 확인자가 이 사전을 사용하여 특정 엔터티 집합에 대한 URI를 반환할 수 있습니다. 샘플 코드가 포함된 더 자세한 예제를 보려면 엔터티 집합 확인자 게시물을 참조하십시오.
버전 관리 요구 사항
DataServiceContext 동작에는 다음과 같은 OData 프로토콜 버전 관리 요구 사항이 있습니다.
Prefer 헤더와 PATCH 요청을 지원하려면 클라이언트와 데이터 서비스 모두 OData 프로토콜 3.0 이상을 지원해야 합니다.
엔터티 집합 확인자를 지원하려면 데이터 프레임워크 릴리스에 WCF Data Services 이상의 클라이언트 라이브러리 버전이 포함되어 있어야 합니다.
자세한 내용은 데이터 서비스 버전 관리(WCF Data Services)을 참조하십시오.