2014-02-17 1 views
4

Azure 테이블 저장소의 일괄 저장 작업에서 이미 존재하는 엔티티의 특정 속성을 효율적으로 바꿀 수 있습니까? 새로운 엔티티의 모든 속성을 업데이트 하시겠습니까?Azure 저장소 및 조건부 대체/병합

여기에 내가 말하고있는 시나리오가 있습니다.

나는 주문라는 실체가

public class Order : TableEntity 
{ 
    public Order(String department, string orderId) 
    { 
     this.PartitionKey = department; 
     this.RowKey = orderId; 
    } 

    public DateTime CreatedOn {get; set;} 
    public String CreatedBy {get; set;} 

    public DateTime UpdatedOn {get; set;} 
    public String UpdatedBy {get; set;} 

    //Class contains other properties which could add up to 1MB 
} 

시나리오

  1. 푸른 표 스토리지 [0..100]
  2. 내 API는 대한 upsert 요청을 수신 RowKeys와 위해서 개체가 있습니다 RowKeys [50..150]로 주문.
  3. 일괄 트랜잭션에서 나는 주문 [50-100]의 특정 속성을 업데이트하고 하늘색에 새로운 주문 엔티티 [101-150]를 생성해야합니다.
  4. 참고 : 기존 주문 [50..100]에서 CreatedOn, CreatedBy, PartitionKey 및 RowKey를 제외한 모든 속성을 업데이트해야합니다.

테이블 스토어에서 내용을 읽지 않고 한 번에 할 수 있습니까? 여기

function Upsert(Dictionary<String, Order> ordersInput) 
{ 
    //1. Read existing ordersInput from database 
    var existingOrders = Retrieve(ordersInput.Values); 

    //2. Update 'ordersInput' with existing data 
    foreach(var existingOrder in existingOrders) 
    { 
     if(ordersInput.ContainsKey(existingOrder.RowKey) 
     { 
      ordersInput[existingOrder.RowKey].CreatedOn = existingOrder.CreatedOn; 
      ordersInput[existingOrder.RowKey].CreatedBy = existingOrder.CreatedBy; 
     } 
    } 

    //Save all merged orders to Azure 
    SaveToAzure(existingOrders); 
} 

나는 위의 방법으로이 문제는 각 주문 개체의 크기가 1MB입니다 및 모든 엔티티를 읽는 것은 아래 습지 있다는 것입니다 그것을 할 수있는 한 가지 방법 (매우 거친 의사 코드)입니다 API 저장 조작.

조건부 병합을 완전히 하늘에서 수행하는보다 효율적인 방법이 있습니까?

나는 또한 다음과 같은 방법

  1. 이전 단계는 "지정된 엔티티가 이미 존재"가 발생하면 모든 주문
  2. 에 배치 삽입를 수행에 배치 삽입을하고 생각했다

    그런 다음 두 개의 새로운 배치 (기존 행 키와 다른 행 키를 각각 하나씩)를 만들고 각각을 개별적으로 처리하십시오.

ounds hacky와 나는 많은 동시성 문제를 야기 할 수 있다고 생각한다.)

+0

해결 했습니까? –

+0

쿼리 투영 및 insertormerge의 조합을 사용했습니다. – infinity

답변

4

Azure 테이블 스토리지 기본적으로 InsertOrReplaceInsertOrMerge 함수를 통해 Upsert 연산을 지원한다. InsertOrReplace은 엔티티를 새로운 엔티티로 완전히 대체합니다. 존재하지 않으면 새로운 엔티티를 생성합니다. InsertOrMerge은 동일한 PartitionKey/RowKey를 갖는 엔티티가 존재하면 새로운 엔티티에 존재하는 기존 엔티티의 속성을 변경합니다. 그렇지 않으면 새로운 엔티티가 생성됩니다.

UPDATE는

여기에 다른 방법입니다.당신이 할 수있는 몇 가지 :

  1. 쿼리 프로젝션 : 쿼리 프로젝션는 기업의 특정 속성을 가져올 수 있습니다. 따라서 기존 엔티티를 가져 오는 경우 PartitionKeyRowKey 만 가져와 엔티티가 이미 존재하는지 여부를 확인할 수 있습니다. 이렇게하면 응답 페이로드가 상당히 줄어 듭니다.
  2. Null 허용 필드 : 기존 엔티티 CreatedOnCreatedBy 필드를 업데이트하지 않기 때문에, 당신은 특히 CreatedOn 그들이 널 수 있도록해야합니다.

이를 기반으로 기존 엔티티를 먼저 가져옵니다. 검색 작업은 쿼리 투영 기술을 사용하여 PartitionKeyRowKey 만 반환합니다. 그런 다음 ordersInput을 반복하고 엔티티가 있는지 확인합니다. 엔터티가 존재하면 CreatedOnCreatedBynull으로 설정하고 해당 엔터티를 Merged으로 표시합니다. 엔터티가 존재하지 않으면 모든 속성을 설정하고 해당 엔터티를 Inserted으로 표시합니다. 그런 다음이 일괄 요청을 테이블 서비스로 보냅니다.

+1

InsertOrMerge 작업을 탐색했지만 앞에서 설명한 시나리오에서는 작동하지 않습니다. 엔터티가 이미 Azure에있는 경우 InsertOrMerge에 특정 속성 업데이트를 건너 뛰도록 지시 할 수 있습니까 (예 : 엔터티가 이미 Azure에 있으면 새 값을 전달할 때도 필드 작성자가 덮어 써서는 안 됨) – infinity

+0

내 대답이 업데이트되었습니다. –

관련 문제