2010-12-17 24 views
13

में इकाई जोड़ें या बदलें, मैं विंडोज़ एज़ूर टेबल स्टोरेज के साथ काम कर रहा हूं और इसकी एक साधारण आवश्यकता है: उस विभाजन के साथ किसी भी मौजूदा पंक्ति को ओवरराइट करने के लिए एक नई पंक्ति जोड़ें। हालांकि, परिवर्तन हमेशा बचत एक अपवाद फेंकता है, भले ही मैं ReplaceOnUpdate विकल्प में पारित: इकाई पहले से मौजूदएज़ूर टेबल स्टोरेज

tableServiceContext.AddObject(TableName, entity); 
tableServiceContext.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate); 

यदि यह फेंकता है:

System.Data.Services.Client.DataServiceRequestException: An error occurred while processing this request. ---> System.Data.Services.Client.DataServiceClientException: <?xml version="1.0" encoding="utf-8" standalone="yes"?> 
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"> 
    <code>EntityAlreadyExists</code> 
    <message xml:lang="en-AU">The specified entity already exists.</message> 
</error> 

मैं वास्तव में मैन्युअल के लिए क्वेरी करने के लिए है मौजूदा पंक्ति पहले और DeleteObject पर कॉल करें? यह बहुत धीमा लगता है। निश्चित रूप से एक बेहतर तरीका है?

उत्तर

14

यदि आप पाते हैं के रूप में, तुम सिर्फ एक और आइटम एक ही पंक्ति कुंजी और विभाजन कुंजी है, इसलिए आप अगर आइटम पहले से मौजूद है देखने के लिए जाँच करने के लिए एक प्रश्न चलाने की आवश्यकता होगी नहीं जोड़ सकते हैं । इस तरह की स्थितियों में मुझे स्टोरेज क्लाइंट लाइब्रेरी में क्या उपलब्ध है यह देखने के लिए Azure REST API documentation पर देखने में मदद मिलती है। आप देखेंगे कि inserting और updating के लिए अलग-अलग विधियां हैं। ReplaceOnUpdate केवल तब प्रभाव पड़ता है जब आप अपडेट कर रहे हों, डालने न दें।

जबकि आप मौजूदा आइटम को हटा सकते हैं और फिर नया जोड़ सकते हैं, तो आप केवल मौजूदा अपडेट कर सकते हैं (आपको स्टोरेज में एक राउंड ट्रिप बचा रहा है)। लेखन के समय जबकि सही सितंबर 2011 अद्यतन माइक्रोसॉफ्ट के साथ Azure तालिका एपीआई अद्यतन किया है दो Upsert आदेश, Insert or Replace Entity और Insert or Merge Entity

शामिल करने के लिए:

var existsQuery = from e 
        in tableServiceContext.CreateQuery<MyEntity>(TableName) 
        where 
        e.PartitionKey == objectToUpsert.PartitionKey 
        && e.RowKey == objectToUpsert.RowKey 
        select e; 

MyEntity existingObject = existsQuery.FirstOrDefault(); 

if (existingObject == null) 
{ 
    tableServiceContext.AddObject(TableName, objectToUpsert); 
} 
else 
{ 
    existingObject.Property1 = objectToUpsert.Property1; 
    existingObject.Property2 = objectToUpsert.Property2; 

    tableServiceContext.UpdateObject(existingObject); 
} 

tableServiceContext.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate); 

संपादित करें: अपने कोड कुछ इस तरह लग सकता है

+0

धन्यवाद, मैंने उस पर विचार किया है, लेकिन इसका मतलब है कि इस कोड को प्रतिलिपि बनाने की आवश्यकता वाले प्रत्येक संपत्ति के बारे में पता होना चाहिए (या इकाई को स्वयं को 'कॉपीटो' विधि की आवश्यकता है) और जब भी गुण बदलते हैं तो उसे अद्यतन करने की आवश्यकता होती है। मुझे लगता है कि मैं हटाए जाने की लागत का भुगतान करना चाहता हूं और सुरक्षित रहूंगा। – EMP

+0

ठीक है, मैं इसे करने के लिए समाप्त हो गया, जितना मैं नहीं चाहता था। इससे कोई फर्क नहीं पड़ता कि मैंने इकाई को हटाने और फिर से सम्मिलित करने का प्रयास कैसे किया, यह वास्तव में काम नहीं करता था - एक बार यह सफल होगा, अगली बार एक त्रुटि के साथ विफल हो जाएंगे, अगली बार किसी और के साथ विफल हो जाएंगे। – EMP

+0

मुझे यह आश्चर्यजनक लगता है। क्या आप एक के हिस्से के रूप में दोनों ऐड और डिलीट को सहेजने की कोशिश कर रहे थे। सेव() कॉल, या आप कर रहे थे .ऑडऑब्जेक्ट(); ।बचाना(); .DeleteObject(); ।बचाना(); – knightpfhor

1

आदेश नहीं हटाने या उसकी ReplaceOnUpdate विकल्पों के साथ SaveChanges, आप AttachTo फोन और TableContext करने के लिए वस्तु देते हैं, बजाय AddObject जो TableContext का निर्देश सम्मिलित करने के लिए प्रयास करने के लिए बुलाने की करने की जरूरत के साथ TableContext द्वारा प्रबंधित किसी मौजूदा ऑब्जेक्ट पर काम करने के लिए यह।

http://msdn.microsoft.com/en-us/library/system.data.services.client.dataservicecontext.attachto.aspx

+0

धन्यवाद, लेकिन मुझे नहीं पता कि इकाई पहले से मौजूद है या नहीं जब मेरी विधि कहलाती है। – EMP

+0

क्षमा करें, प्रारंभिक समस्या को ध्यान से पर्याप्त रूप से नहीं पढ़ा। आपको हाथ से पहले पढ़ना होगा। हालांकि उस पंक्ति को हटाने की जरूरत नहीं है। यदि पंक्ति मौजूद है या डालने पर डालें तो बस एक अपडेट करें। इसे टालना नहीं। – Igorek

1

मेरे मामले में इसे पहले इसे हटाने की अनुमति नहीं थी, इस प्रकार मैं इसे इस तरह से करता हूं, इसके परिणामस्वरूप सर्वर पर एक लेनदेन होगा जो पहले मौजूदा ऑब्जेक्ट को हटा देगा और नया जोड़ देगा, संपत्ति मूल्यों की प्रतिलिपि बनाने की आवश्यकता को हटा देगा

 var existing = from e in _ServiceContext.AgentTable 
         where e.PartitionKey == item.PartitionKey 
          && e.RowKey == item.RowKey 
         select e; 

     _ServiceContext.IgnoreResourceNotFoundException = true; 
     var existingObject = existing.FirstOrDefault(); 

     if (existingObject != null) 
     { 
      _ServiceContext.DeleteObject(existingObject); 
     } 

     _ServiceContext.AddObject(AgentConfigTableServiceContext.AgetnConfigTableName, item); 

     _ServiceContext.SaveChangesWithRetries(); 
     _ServiceContext.IgnoreResourceNotFoundException = false; 
+0

मुझे लगता है कि आपको हुड के नीचे वास्तव में क्या हो रहा है यह देखने की आवश्यकता हो सकती है। जहां तक ​​मुझे पता है कि अंतर्निहित आरईएसटी एपीआई एक कॉल में जोड़ों और हटाए जाने से निपट नहीं सकती है। तो जब आप बस कॉल कर रहे हैं .व() एक बार, यह स्टोरेज सेवा में दो कॉल भेज देगा। – knightpfhor

0

भंडार एपीआई एक समूह के लेनदेन में इकाई प्रति एक से अधिक आपरेशन (+ डालने हटाना) अनुमति नहीं देता:

एक इकाई लेन-देन में केवल एक बार दिखाई दे सकता है, और केवल एक आपरेशन इसके खिलाफ प्रदर्शन किया जा सकता ।

MSDN: Performing Entity Group Transactions

तो वास्तव में आप पहली बार पढ़ सकते हैं और डालने या अद्यतन पर फैसला करने की जरूरत है देखते हैं।

0

Insert/Merge or Update सितंबर 2011 में एपीआई में जोड़ा गया था। यहां स्टोरेज एपीआई 2.0 का उपयोग करने का एक उदाहरण है जो इसे समझने में आसान है, जिस तरह से इसे 1.7 एपीआई और पहले किया जाता है।

public void InsertOrReplace(ITableEntity entity) 
    { 
     retryPolicy.ExecuteAction(
      () => 
      { 
       try 
       { 
        TableOperation operation = TableOperation.InsertOrReplace(entity); 
        cloudTable.Execute(operation); 
       } 
       catch (StorageException e) 
       { 
        string message = "InsertOrReplace entity failed."; 

        if (e.RequestInformation.HttpStatusCode == 404) 
        { 
         message += " Make sure the table is created."; 
        } 

        // do something with message 
       } 
      }); 
    } 
+0

आशावादी समेकन के साथ करने के लिए, इस कोड में एक गॉचा है। आपको लगता है कि "InsertOrReplace" "सम्मिलित करें" और "प्रतिस्थापन" जैसा काम करता है, जब तक कि आपने पिछली बार जांच नहीं की है तब तक रिकॉर्ड को तब तक बदल दिया जाएगा जब तक कि आपने इसे चेक नहीं किया है। लेकिन यह गलत होगा। "InsertOrReplace" का अर्थ वास्तव में है "उस रिकॉर्ड को ओवरराइट करें चाहे कोई फर्क नहीं पड़ता, और आशावादी समरूपता जांच को अनदेखा करें"। तो अगर आपको आशावादी समेकन की परवाह नहीं है तो महान! अन्यथा, आप शायद इसे "अप्सर्ट" के रूप में उपयोग नहीं करना चाहते हैं। – AndyJ

संबंधित मुद्दे