2012-03-30 10 views
9

साथ (आईडी के आधार पर) 2100 से अधिक पंक्तियों को हटाने का सही विधि मैं अपने सर्वर अनुप्रयोग के लिए Dapper समर्थन मेरे डेटा का उपयोग का उपयोग करने की कोशिश कर रहा हूँ।डैप्पर

मेरे सर्वर ऐप में एक और एप्लीकेशन है जो 400 मिनट प्रति मिनट की दर से मेरे डेटाबेस में रिकॉर्ड छोड़ देता है।

मेरे एप्लिकेशन उन्हें, बैचों में बाहर खींचती उन्हें संसाधित करता है, और फिर उन्हें डेटाबेस से हटा देता है।

के बाद से डेटा डेटाबेस में प्रवाह करने के लिए जब मैं प्रसंस्करण कर रहा हूँ जारी है, मैं एक अच्छा तरीका delete from myTable where allProcessed = true कहने के लिए नहीं है।

हालांकि, मुझे पता लगाने के लिए पंक्तियों का पीके मान पता है। तो मैं delete from myTable where Id in @listToDelete

समस्या यह है कि यदि मेरा सर्वर 6 मिनट तक भी नीचे चला जाता है, तो मेरे पास 2100 से अधिक पंक्तियां हटाना है।

के बाद से साफ-सुथरी मेरी @listToDelete लेता है और एक पैरामीटर में हर एक को बदल जाता है, को नष्ट करने के लिए अपने कॉल विफल रहता है। (यहां तक ​​कि आगे पीछे पाने के लिए शुद्धिकरण अपने डेटा के कारण।)

डैप्पर में इस समस्या से निपटने का सबसे अच्छा तरीका क्या है?

नोट्स: मैंने टेल्ड वैल्यूड पैरामीटर्स को देखा है लेकिन जो मैं देख सकता हूं, वे performant नहीं हैं। मेरे आर्किटेक्चर का यह टुकड़ा मेरे सिस्टम की बोतल गर्दन है और मुझे बहुत बहुत तेज होना चाहिए।

+0

@marc_s - मुझे ** कई पैरामीटर पास करने के लिए ** ** की आवश्यकता नहीं है ... लेकिन मुझे पीके आईडी द्वारा कई पंक्तियों को हटाने की आवश्यकता है। हालांकि मैं करता हूं कि यह मेरे द्वारा ठीक है। मैं अपनी '@ सूची' में हर पंक्ति को हटाने के लिए डैपर को बता रहा हूं। यह डैपर है जो मेरी सूची में प्रत्येक आइटम के पैरामीटर बना रहा है। – Vaccano

+0

इस छोटी जानकारी से बताना मुश्किल है, लेकिन आप हटाए जाने के लिए अपने मानदंड के रूप में बैच के लिए टीएच चयन मानदंड का उपयोग क्यों नहीं कर सकते हैं। या MyTable में एक संसाधित ध्वज है, इसे "प्रसंस्करण" में सेट करें और उसके बाद इसका उपयोग करें। यह ब्रिल नहीं है, लेकिन यह एक-एक करके उन्हें हटाने से बहुत तेज़ होगा। 10,000 रिकॉर्ड के साथ भी यह चौंकाने वाला नहीं होगा। –

+0

मेरा बैच मानदंड बहुत प्रदर्शन नहीं करता है। तो मैं इसका उपयोग नहीं करना पसंद करूंगा। मैं एक संसाधित ध्वज जोड़ सकता हूं, लेकिन ऐसा करने के लिए मुझे संसाधित ध्वज जोड़ने के लिए पंक्तियों को कॉल करने का एक तरीका चाहिए। अगर मैं उन्हें बुला सकता हूं, तो मैं उन्हें भी हटा सकता हूं। (मैं चुनने के लिए एक झंडा जोड़ सकता हूं, चुनिंदा समय पर "बैच"। लेकिन मैं नहीं चाहूंगा।) – Vaccano

उत्तर

12

एक विकल्प सर्वर पर एक अस्थायी तालिका बनाने और फिर उस तालिका में एक ही बार में सभी आईडी अपलोड करने के लिए थोक लोड सुविधा का उपयोग करने के लिए है। फिर केवल अपने रिकॉर्ड तालिका में अपलोड किए गए रिकॉर्ड को हटाने के लिए एक जॉइन, EXISTS या IN Clause का उपयोग करें।

थोक लोड SQL सर्वर में एक अच्छी तरह से अनुकूलित पथ हैं और यह बहुत तेज़ होना चाहिए।

उदाहरण के लिए:

  1. बयान CREATE TABLE #RowsToDelete(ID INT PRIMARY KEY)
  2. उपयोग #RowsToDelete
  3. में कुंजी सम्मिलित करने के लिए निष्पादित DELETE FROM myTable where Id IN (SELECT ID FROM #RowsToDelete)
  4. निष्पादित DROP TABLE #RowsToDelte एक थोक लोड निष्पादित (टेबल भी स्वतः ही यदि आप इसे बंद गिरा दिया जाएगा सत्र)

(यह मानते हुए डैप्पर) कोड उदाहरण:

conn.Open(); 

var columnName = "ID"; 

conn.Execute(string.Format("CREATE TABLE #{0}s({0} INT PRIMARY KEY)", columnName)); 

using (var bulkCopy = new SqlBulkCopy(conn)) 
{ 
    bulkCopy.BatchSize = ids.Count; 
    bulkCopy.DestinationTableName = string.Format("#{0}s", columnName); 

    var table = new DataTable();      
    table.Columns.Add(columnName, typeof (int)); 
    bulkCopy.ColumnMappings.Add(columnName, columnName); 

    foreach (var id in ids) 
    { 
     table.Rows.Add(id); 
    } 

    bulkCopy.WriteToServer(table); 
} 

//or do other things with your table instead of deleting here 
conn.Execute(string.Format(@"DELETE FROM myTable where Id IN 
            (SELECT {0} FROM #{0}s", columnName)); 

conn.Execute(string.Format("DROP TABLE #{0}s", columnName)); 
+0

वास्तव में एसक्यूएलकल्क कॉपी का उपयोग करने वाला उदाहरण कोड जोड़ा गया है, जिसे अस्थायी रूप से अधिक कॉलम जोड़कर व्यापक तालिकाओं के लिए अनुकूलित किया जा सकता है टेबल और डेटा टेबल। –

5

इस कोड को काम करने के लिए, मैं अंधेरा पक्ष चला गया।

चूंकि डैपर मेरी सूची पैरामीटर में बनाता है। और SQL सर्वर कई पैरामीटर को संभाल नहीं सकता है। (मुझे पहले कभी भी दो अंकों के मानकों की आवश्यकता नहीं है)। मुझे गतिशील एसक्यूएल के साथ जाना पड़ा।

तो यहाँ मेरी समाधान था:

string listOfIdsJoined = "("+String.Join(",", listOfIds.ToArray())+")"; 
connection.Execute("delete from myTable where Id in " + listOfIdsJoined); 

से पहले हर किसी को पकड़ लेता है उनके मशालों और pitchforks, मुझे समझाती हूँ।

  • यह कोड उस सर्वर पर चलता है जिसका एकमात्र इनपुट मेनफ्रेम सिस्टम से डेटा फ़ीड है।
  • जिस सूची में मैं गतिशील रूप से निर्माण कर रहा हूं वह लंबी/bigints की एक सूची है।
  • लम्बा/bigints पहचान कॉलम से हैं।

मुझे पता है कि गतिशील एसक्यूएल का निर्माण बुरा जुजू है, लेकिन इस मामले में, मैं नहीं देख सकता कि यह सुरक्षा जोखिम की ओर कैसे जाता है।

+2

[लिटिल बॉबी टेबल्स] (https://xkcd.com/327/) कहते हैं G'Day! –

+3

@ शुद्ध। क्रोम संभवतः उसकी 'सूचीऑफआईड्स' प्रकार 'सूची ' है इसलिए इनपुट – Zac

+0

इनपुट को संतोषजनक करने की आवश्यकता नहीं है ... लेकिन धारणाएं सभी बुराइयों की जड़ हैं। दूसरा, यह सामान्य सुझाव => फ्लाई पर और एक स्ट्रिंग में एक एसक्यूएल स्क्रिप्ट बनाना ... बहुत बुरी तरह समाप्त हो सकता है :) –

2

उपरोक्त मामले में साफ-सुथरी अनुरोध एक संपत्ति के रूप में वस्तु होने पैरामीटर की सूची तो ईद होने के रूप में संपत्ति काम करेंगे वस्तु की एक सूची।

connection.Execute("delete from myTable where Id in (@Id)", listOfIds.AsEnumerable().Select(i=> new { Id = i }).ToList()); 

यह काम करेगा।

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