2013-07-05 3 views
2

내가 이러한 조건에서 푸른 스토리지 테이블에 개체를 삽입 할 수 있어야합니다 (이 *의 경우를 제외하고) 삽입에 예외를 던져의 ETag를 사용하는 방법 :의 ETag가 일치하지 않는 경우

  • 이 경우 존재하지 않습니다. 삽입하십시오.
  • (있는 경우), ETag를 *로 지정하고 바꾸십시오.
  • ETag에 다른 값이있는 경우 코드 409 또는 412로 StorageException을 throw합니다. 예를 들어 검색 한 엔티티를 삽입하려고 시도하지만 그 동안에는 다른 곳에서 업데이트하려고 시도합니다.

이 간단한 프로그램을 테스트했지만이 방법을 알 수는 없습니다. 그것은 결코 예외에 도달하지 않습니다. (나는 이것이 정규 ETag 행동 요구 사항이라고 생각했다).

삽입 작업을 InsertOrReplace 대신 사용하면 ETag에 변경되지 않은 값이 있어도 예외가 발생합니다.

 CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnString); 
     CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); 
     tableClient.RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(3), 10); 
     var testtable = tableClient.GetTableReference("davidstesttable"); 
     testtable.CreateIfNotExists(); 

     //insert first entity 
     var newentity = new DynamicTableEntity("idunno", String.Empty, "*", new Dictionary<string, EntityProperty> { { "testprop", new EntityProperty("testval") } }); 
     Msg("insert initial entity"); 
     testtable.Execute(TableOperation.InsertOrReplace(newentity)); 
     Msg("inserted"); 

     Msg("retrieving"); 
     TableResult tableResult = testtable.Execute(TableOperation.Retrieve("idunno", String.Empty)); 
     DynamicTableEntity firstRetrieve = (DynamicTableEntity)tableResult.Result; 
     Msg("retrieved. etag: " + firstRetrieve.ETag); 

     Msg("inserting the initial entity again to change the ETag in the table"); 
     testtable.Execute(TableOperation.InsertOrReplace(newentity)); 
     Msg("inserted"); 

     Msg("retrieving"); 
     TableResult tableResult2 = testtable.Execute(TableOperation.Retrieve("idunno", String.Empty)); 
     DynamicTableEntity secondRetrieve = (DynamicTableEntity)tableResult2.Result; 
     Msg("retrieved. etag: " + secondRetrieve.ETag); 

     if(firstRetrieve.ETag != secondRetrieve.ETag) 
     { 
      Msg("confirmed entity in table now has different etag"); 
      Msg("inserting the first retrieved. (etags should not match now, expecting StorageException)"); 
      try 
      { 
       //If I use Insert operation instead of InsertOrReplace, I do get the exception, 
       //but I tested with this and then I get the exception even if the ETag is unchanged or * ! 
       testtable.Execute(TableOperation.InsertOrReplace(firstRetrieve)); 
       Msg("hmm should not have reached here!"); 
      } 
      catch (StorageException e) 
      { 
       if(e.RequestInformation.HttpStatusCode == 409 || e.RequestInformation.HttpStatusCode == 412) 
        Msg("got exception as expected because of the mismatching ETag."); 
      } 
     } 
+0

엔티티에 이미 ETag가있는 경우 엔티티가 있음을 알 수 있습니다. 왜'InsertOrReplace' 대신에'Update'를 사용하지 않겠습니까? –

답변

8

해결책을 찾았을 수도 있습니다. 아무도 더 좋은 대답이 없다면 이것을 받아 들일 것입니다.

OperationContextIf-Match 헤더를 값으로 Etag와 함께 추가하려고했습니다. 이것은 효과가 있었다. 나는 이것이 자동으로 추가 된 것이라고 생각했지만 명백하게는 그렇지 못했다. 이제

testtable.Execute(
    TableOperation.InsertOrReplace(firstRetrieve), 
    null, 
    new OperationContext { 
    UserHeaders = new Dictionary<String, String> 
         { 
         { "If-Match", firstRetrieve.ETag } 
         } 
    } 
); 

,의 ETag로 null를 사용하여, 나는 InsertOrReplace을 할 수있는, 그리고 뭔가 다른 경우도 제대로있는 ETag를 확인합니다.

ETag로 *을 사용하면 엔티티가 존재하지 않으면 404 예외가 발생합니다. 따라서 의도 된 기능을 사용하려면 null을 사용하십시오. 또는 * 만 감지하고 헤더를 추가하지 마십시오.

편집 :

경고 : 새 항목 (있는 ETag의 == null)를 삽입하고 싶지만 아직이 이미 존재하는 경우 예외 코드 (409) 충돌을 얻을 싶어 경우, 대신 Insert 작업을 사용해야합니다 InsertOrReplace 작업의