2010-10-12 29 views
21

मैं सरल ऑब्जेक्ट की सूची < सूची से SqlBulkCopy के साथ एक बड़ा सम्मिलन कैसे कर सकता हूं?सूची से SqlBulkCopy <>

क्या मैं अपना कस्टम IDataReader लागू करता हूं?

+0

देर पार्टी के लिए , लेकिन यदि आप इस 'EntityDataReader' वर्ग को जोड़ते हैं, तो वहां' AsDataReader() 'एक्सटेंशन विधि है जो ठीक है: https: // github।com/matthewschrager/भंडार/ब्लॉब/मास्टर/Repository.EntityFramework/EntityDataReader.cs – RJB

+0

(पूर्ण कार्यान्वयन के लिए नीचे दिए गए नए जवाब देखें) – RJB

उत्तर

19

ऑब्जेक्ट्स की अपनी सूची से create a DataTable और डेटा तालिका पास करने से SqlBulkCopy.WriteToServer पर कॉल करें।

आप उपयोगी निम्नलिखित हो सकते हैं:

  • Adding columns to a DataTable। प्रत्येक संपत्ति/फ़ील्ड के लिए एक कॉलम जोड़ें जिसे आप लिखना चाहते हैं।
  • Adding rows to a DataTable। अपनी सूची में प्रत्येक ऑब्जेक्ट के लिए एक पंक्ति जोड़ें।

एसकब्लूल्ककॉपी के साथ अधिकतम प्रदर्शन के लिए, आपको उपयुक्त BatchSize सेट करना चाहिए। 10,000 अच्छी तरह से काम करता प्रतीत होता है - लेकिन आपके डेटा के लिए प्रोफ़ाइल।

SqlBulkCopyOptions.TableLock का उपयोग करते समय आप बेहतर परिणाम भी देख सकते हैं।

एसकब्लूल्ककॉपी प्रदर्शन का एक दिलचस्प और सूचनात्मक विश्लेषण here पाया जा सकता है।

using(var bcp = new SqlBulkCopy(connection)) 
using(var reader = ObjectReader.Create(data, "Id", "Name", "Description")) 
{ 
    bcp.DestinationTableName = "SomeTable"; 
    bcp.WriteToServer(reader); 
} 

ध्यान दें कि ObjectReader भी गैर के साथ काम कर सकते हैं:

40
FastMember साथ

, क्या आपने कभी DataTable (जो, मेरे परीक्षणों में, प्रदर्शन और अधिक से अधिक युगल) के माध्यम से जाने के लिए की जरूरत के बिना ऐसा कर सकते हैं जेनेरिक स्रोत, और सदस्य-नामों को अग्रिम में निर्दिष्ट करना आवश्यक नहीं है (हालांकि आप शायद SqlBulkCopy के ColumnMappings पहलू का उपयोग करना चाहते हैं यदि आप उन्हें ObjectReader में निर्दिष्ट नहीं करते हैं)।

+0

उत्कृष्ट पुस्तकालय! मैंने अभी अभी कोशिश की है और यह बहुत अच्छा काम करता है। – alex

+0

मुझे पता है कि यह कुछ महीने पहले से था, लेकिन मुझे एक समान समस्या है। पहले 'डेटाटेबल' लोड करने में बहुत समय लगता है, इसलिए मैं इस विधि का उपयोग करना चाहता था। हालांकि पैराम में सूचीबद्ध स्ट्रिंग्स ऑब्जेक्ट से अंतर्निहित डेटा संरचना के ऑब्जेक्ट के क्रम में उपयोग किए जा रहे चर के वास्तविक नामों को बदलती हैं? – JNYRanger

+0

स्क्रैच करें - इसे समझ लिया और जवाब हाँ था, वे ऑब्जेक्ट के भीतर गुणों के नाम हैं। – JNYRanger

1

पहली जगह में SqlBulkCopy पर कॉल करके आप जो पूरा करने की कोशिश कर रहे हैं उसके आधार पर, यह तालिका-मूल्यवान पैरामीटर (टीवीपी) का उपयोग करने के लिए अधिक समझदारी कर सकता है। एक टीवीपी का उपयोग करना किसी भी कस्टम प्रकार के संग्रह में भेजने के लिए तुच्छ हो जाएगा। डेटा को स्ट्रीम किया जा सकता है ताकि आप DataTable (@Marc Gravell के उत्तर में जैसे) से बच सकें और आप SqlBulkCopy से भी बच सकते हैं। टीवीपी डेटा को पास करने के लिए संग्रहीत प्रक्रिया को कॉल करने के बाद टीवीपी को SQL सर्वर पर पहुंचने के तरीके को पूरी तरह से लचीलापन की अनुमति देता है और यह तालिका वैरिएबल के रूप में दिखाई देता है जिसे आप कुछ भी कर सकते हैं, न केवल INSERT (जो कि है SqlBulkCopy के साथ मामला)। आप SqlDataReader के माध्यम से डेटा वापस प्राप्त कर सकते हैं, नए बनाए गए IDENTITY मान जैसे डेटा। मैंने इस उत्तर पर एक उदाहरण और कुछ अतिरिक्त नोट्स जोड़े: How can I insert 10 million records in the shortest time possible?। और कई साल पहले मैंने एसक्यूएल सर्वर सेंट्रल (मुफ्त पंजीकरण आवश्यक), Streaming Data Into SQL Server 2008 From an Application पर एक लेख लिखा था, जो उस लिंक किए गए उत्तर में भी उल्लेख किया गया है, जो एक कस्टम प्रकार की जेनेरिक सूची में गुजरने का एक उदाहरण उदाहरण प्रदान करता है, जो 3 मिलियन से स्ट्रीम किया गया है पंक्ति पाठ फ़ाइल।

5

पार्टी के लिए देर हो चुकी है, लेकिन यदि आप Microsoft से इस EntityDataReader वर्ग जोड़ने के लिए, वहाँ एक AsDataReader() विस्तार विधि है कि वास्तव में करता है: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs

(उदाहरण के [List].AsDataReader() कार्यान्वयन :)

var connStr = ""; 
using (var connection = new SqlConnection(connStr)) 
{ 
    var startTime = DateTime.Now; 
    connection.Open(); 
    var transaction = connection.BeginTransaction(); 
    try 
    { 
     //var connStr = connection.ConnectionString; 
     using (var sbCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction)) 
     { 
      sbCopy.BulkCopyTimeout = 0; 
      sbCopy.BatchSize = 10000; 
      sbCopy.DestinationTableName = "Foobars"; 
      var reader = Foobars.AsDataReader(); 
      sbCopy.WriteToServer(reader); 
     } 
     transaction.Commit(); 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex.Message); 
     transaction.Rollback(); 
    } 
    finally 
    { 
     transaction.Dispose(); 
     connection.Close(); 
     var endTime = DateTime.Now; 
     Console.WriteLine("Upload time elapsed: {0} seconds", (endTime - startTime).TotalSeconds); 
    } 
} 
संबंधित मुद्दे