2010-05-21 26 views
6

मुझे आश्चर्य है कि बैच अपडेट करने का कोई तरीका है? मैं एमएस एसक्यूएल सर्वर 2005 का उपयोग कर रहा हूं।बैच अपडेट कैसे करें?

मैंने sqlDataAdaptor से दूर देखा लेकिन ऐसा लगता है कि आपको इसके साथ पहले चयन कथन करना होगा, फिर कुछ डेटासेट भरें और डेटासेट में परिवर्तन करें।

अब मैं चयन करने के लिए एसक्यूएल के लिए linq का उपयोग कर रहा हूं इसलिए मैं इसे इस तरह से रखने की कोशिश करना चाहता हूं। हालांकि बड़े पैमाने पर अपडेट करना बहुत धीमा है। तो क्या वहां है कि मैं अपने linq को sql (चुनिंदा भाग के लिए) में रख सकता हूं लेकिन बड़े पैमाने पर अद्यतन करने के लिए कुछ अलग उपयोग कर सकता हूं?

धन्यवाद

संपादित

मैं इस मचान तालिका में दिलचस्पी है, लेकिन मैं कैसे स्पष्ट नहीं यह करना है और अभी भी करने के लिए यकीन नहीं है कि यह कैसे तेजी के बाद से मुझे समझ नहीं आता कैसे हो जाएगा भाग काम अद्यतन करें।

तो क्या कोई मुझे दिखा सकता है कि यह कैसे काम करेगा और समवर्ती कनेक्शन से कैसे निपटें?

EDIT2

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

using (TestDataContext db = new TestDataContext()) 
      { 
       UserTable[] testRecords = new UserTable[2]; 
       for (int count = 0; count < 2; count++) 
       { 
        UserTable testRecord = new UserTable(); 

        if (count == 1) 
        { 
         testRecord.CreateDate = new DateTime(2050, 5, 10); 
         testRecord.AnotherField = true; 
        } 
        else 
        { 
         testRecord.CreateDate = new DateTime(2015, 5, 10); 
         testRecord.AnotherField = false; 
        } 


        testRecords[count] = testRecord; 
       } 

       StringBuilder sBuilder = new StringBuilder(); 
       System.IO.StringWriter sWriter = new System.IO.StringWriter(sBuilder); 
       XmlSerializer serializer = new XmlSerializer(typeof(UserTable[])); 
       serializer.Serialize(sWriter, testRecords);    

       using (SqlConnection con = new SqlConnection(connectionString)) 
       { 
        string sprocName = "spTEST_UpdateTEST_TEST"; 

        using (SqlCommand cmd = new SqlCommand(sprocName, con)) 
        { 
         cmd.CommandType = CommandType.StoredProcedure; 

         cmd.CommandType = System.Data.CommandType.StoredProcedure; 

         SqlParameter param1 = new SqlParameter("@UpdatedProdData", SqlDbType.VarChar, int.MaxValue); 
         param1.Value = sBuilder.Remove(0, 41).ToString(); 
         cmd.Parameters.Add(param1); 
         con.Open(); 
         int result = cmd.ExecuteNonQuery(); 
         con.Close(); 
        } 
       } 
      } 

@ फ्रेडरिक जोहानसन मुझे यकीन नहीं है कि आपकी कहानियां क्या काम करेगी। ऐसा लगता है कि मैं चाहता हूं कि आप मुझे प्रत्येक रिकॉर्ड के लिए एक अपडेट स्टेटमेंट बनाना चाहते हैं। मैं ऐसा नहीं कर सकता क्योंकि मुझे 1 से 50,000+ रिकॉर्ड अपडेट करने की आवश्यकता होगी और मुझे उस बिंदु तक पता नहीं चलेगा।

संपादित 3

तो यह मेरी सपा अब है। मुझे लगता है कि यह समवर्ती कनेक्शन करने में सक्षम होना चाहिए लेकिन मैं सुनिश्चित करना चाहता था।

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE PROCEDURE [dbo].[sp_MassUpdate] 
@BatchNumber uniqueidentifier 
AS 
BEGIN 
    update Product 
    set ProductQty = 50 
    from Product prod 
    join StagingTbl stage on prod.ProductId = stage.ProductId 
    where stage.BatchNumber = @BatchNumber 

    DELETE FROM StagingTbl 
    WHERE BatchNumber = @BatchNumber 

END 
+0

क्या आप अपनी टिप्पणी को समझा सकते हैं/औचित्य साबित कर सकते हैं। LINQ-to-SQL अद्यतन प्रदर्शन समस्याएं? –

+0

असल में यह नीचे आता है। मैं 500 रिकॉर्ड डालना चाहता था और 500 रिकॉर्ड अपडेट करना चाहता था। प्रमाणीकरण में 1min और 58 सेकंड लग गए, थोक प्रतिलिपि के साथ डालने से 2 सेकंड्स ले गए और सभी 500 पंक्तियों को अपडेट करने के लिए linq का उपयोग करके एसक्यूएल का उपयोग करके उन्हें 4 मिनट लग गए। मैं इसे नीचे ले जाना चाहता हूं क्योंकि मुझे शायद 30,000 से 50,000 पंक्तियों के ऊपर अपडेट करने की आवश्यकता होगी। हालांकि मैं चयन और हेरफेर करने के लिए linq को sql नहीं करना चाहता क्योंकि मुझे किसी ऑब्जेक्ट के साथ काम करना आसान लगता है। मुझे यह पता नहीं चलता कि यह अपडेट की बात आती है जब यह दिखता है क्योंकि यह आसान होना चाहिए क्योंकि मेरे पास सभी रिकॉर्ड्स में हेरफेर किया गया है और मैं सिर्फ – chobo2

+0

प्रत्येक लिनक ऑब्जेक्ट के मानों को लूप के साथ निकाल सकता हूं और इसे फेंक सकता हूं कभी जरूरी है – chobo2

उत्तर

1

जैसा कि सभी नाम कहा गया है, एसकब्लूल्ककॉपी का उपयोग करें, जो बहुत तेज़ है (मुझे 200x से अधिक की गति में सुधार हुआ - 1500 सेकेंड से 6 एस तक)। हालांकि आप SQlBulkCopy (जो आसान लगता है) को डेटा प्रदान करने के लिए डेटाटेबल और डेटारो कक्षाओं का उपयोग कर सकते हैं। SqlBulkCopy का उपयोग इस तरह से बीन .NET 3.0 के साथ-साथ लाभ का अतिरिक्त लाभ भी है (लिंक केवल 3.5 में जोड़ा गया था)। कुछ नमूना कोड के लिए
चेकआउट http://msdn.microsoft.com/en-us/library/ex21zs8x%28v=VS.100%29.aspx

0

आपको सीधे अभिव्यक्ति पेड़ों के साथ काम करना है, लेकिन यह करने योग्य है। वास्तव में, यह पहले से ही आप के लिए किया गया है, तो आप सिर्फ स्रोत डाउनलोड करने के लिए है:

Batch Updates and Deletes with LINQ to SQL

विकल्प सिर्फ संग्रहित प्रक्रियाओं या तदर्थ एसक्यूएल प्रश्नों का उपयोग करने के लिए DataContext की ExecuteMethodCall और ExecuteCommand तरीकों का उपयोग कर रहा है ।

+0

तक पहुंच होगी इस विकल्प को समझाओ? मुझे कोई परवाह नहीं है कि अद्यतन भाग एक एसपी या ado.net में है, जिसकी मुझे परवाह है, उस पर निर्भर करता है कि मेरे पास linq में sql में चयन और हेरफेर है, इसलिए मैं ऑब्जेक्ट्स से निपट सकता हूं। मैंने उन्हें छेड़छाड़ करने के बाद मुझे परवाह नहीं है कि वे डेटाबेस में कैसे अपडेट हो जाते हैं। – chobo2

+0

@ chobo2: मुझे यकीन नहीं है कि क्या समझाया जा सकता है - यदि आप संग्रहीत प्रक्रिया के रूप में पूरी तरह से सर्वर पर अपना अपडेट तर्क लिख सकते हैं, तो बस उस एसपी को लिंक में SQL डिजाइनर सतह पर खींचें और इसे चलाएं। यद्यपि आप रिकॉर्ड-दर-रिकॉर्ड में मदद नहीं करेंगे, अगर आप हजारों रिकॉर्ड में अलग-अलग अपडेट करने की कोशिश कर रहे हैं; उस प्रक्रिया को तेज़ करने का एकमात्र तरीका एक तालिका-मूल्यवान पैरामीटर, या एक स्टेजिंग टेबल में थोक डालने का उपयोग करना है, न कि लिंक से SQL का समर्थन करता है। – Aaronaught

+0

यह स्टेजिंग टेबल कैसे काम करेगी? – chobo2

1

एसक्यूएलकल्क कॉपी का उपयोग करें, जो बिजली-तेज है। आपको एक कस्टम IDataReader कार्यान्वयन की आवश्यकता होगी जो आपके linq क्वेरी परिणामों पर आधारित है। अधिक जानकारी और कुछ संभावित उपयुक्त IDataReader कोड के लिए http://code.msdn.microsoft.com/LinqEntityDataReader पर देखें।

1

आप बैच अपडेट करने के लिए sqlDataAdapter का उपयोग कर सकते हैं। इससे कोई फर्क नहीं पड़ता कि आप अपना डेटासेट कैसे भरते हैं। L2SQL या जो भी हो, आप अद्यतन करने के लिए विभिन्न विधियों का उपयोग कर सकते हैं। अपने डेटाटेबल में डेटा का उपयोग करके चलाने के लिए क्वेरी को बस परिभाषित करें।

यहां कुंजी अपडेटबैचसाइज है। डेटाएडाप्टर आपके द्वारा परिभाषित किए गए आकार के बैच में अपडेट भेज देगा। यह मूल्य देखने के लिए आपको इस मूल्य के साथ समाप्त होने की आवश्यकता है कि कौन सा नंबर सबसे अच्छा काम करता है, लेकिन 500-1000 की सामान्य संख्या सर्वोत्तम होती है।एसक्यूएल फिर अद्यतन को अनुकूलित कर सकता है और थोड़ा तेज निष्पादित कर सकता है। ध्यान दें कि बैचअपडेट्स करते समय, आप डेटाटेबल के पंक्ति स्रोत को अपडेट नहीं कर सकते हैं।

मैं 10-100K के अपडेट करने के लिए इस विधि का उपयोग करता हूं और यह सामान्यतः 2 मिनट से कम समय में चलता है। यह उस पर निर्भर करेगा जो आप अपडेट कर रहे हैं।

क्षमा करें, यह वीबी में है ...।

Using da As New SqlDataAdapter 
     da.UpdateCommand = conn.CreateCommand 
     da.UpdateCommand.CommandTimeout = 300 

     da.AcceptChangesDuringUpdate = False 
     da.ContinueUpdateOnError = False 
     da.UpdateBatchSize = 1000 ‘Expirement for best preformance 
     da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None 'Needed if UpdateBatchSize > 1 
     sql = "UPDATE YourTable" 
     sql += " SET YourField = @YourField" 
     sql += " WHERE ID = @ID" 
     da.UpdateCommand.CommandText = sql 
     da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None 
     da.UpdateCommand.Parameters.Clear() 
     da.UpdateCommand.Parameters.Add("@YourField", SqlDbType.SmallDateTime).SourceColumn = "YourField" 
     da.UpdateCommand.Parameters.Add("@ID", SqlDbType.SmallDateTime).SourceColumn = "ID" 

     da.Update(ds.Tables("YourTable”) 
End Using 

एक और विकल्प एक temp तालिका में bulkcopy है, और उसके बाद से मुख्य तालिका अद्यतन करने के लिए एक क्वेरी चलाएँ। यह तेज़ हो सकता है।

0

आप बैच-अपडेट करने के लिए SqlDataAdapter का उपयोग कर सकते हैं भले ही एक डेटाटेबल मैन्युअल रूप से/प्रोग्रामेटिक रूप से भर दिया गया हो (किसी अन्य स्रोत के linq से)।

बस डेटाटेबल में पंक्तियों के लिए RowState मैन्युअल रूप से सेट करना याद रखें। इसके लिए dataRow.SetModified() का उपयोग करें।

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