2015-10-28 10 views
14

मैं धाराप्रवाह NHibernate का उपयोग करने के लिए एक डेटाबेस है कि डेटाबेस में से कुछ की जरूरत है स्थानांतरित करने के लिए कोशिश कर रहा हूँ 'की मालिश'। स्रोत डेटाबेस एक एमएस एक्सेस डेटाबेस है और वर्तमान तालिका जो मैं फंस गया हूं वह ओएलई ऑब्जेक्ट फ़ील्ड वाला है। लक्ष्य डेटाबेस एक एमएस एसक्यूएल सर्वर एक्सप्रेस डेटाबेस है।NHibernate OutOfMemoryException से क्वेरी बड़े बाइट []

इकाई में मैं तो बस इस फ़ील्ड लेकिन जब तथापि लोड हो रहा है तब भी जब बस लोड हो रहा है कि एक ही रिकार्ड के लिए एक क्षेत्र मैं एक System.OutOfMemoryException

byte[] test = aSession.Query<Entities.Access.Revision>().Where(x => x.Id == 5590).Select(x => x.FileData).SingleOrDefault<byte[]>(); 

मैं तो लागू करने की कोशिश की मार गया था एक byte[] के रूप में परिभाषित किया था blob type listed here लेकिन अब जब चल रहा की कोई त्रुटि प्राप्त है कि:

" 'System.Byte []' टाइप प्रकार की वस्तु कास्ट करने में असमर्थ के लिए 'TestProg.DatabaseConverter.Entities.Blob'।"}

मैं कल्पना नहीं कर सकते ओले वस्तु किसी भी 100MB से अधिक है, लेकिन नहीं की जाँच करने में सक्षम है। वहाँ धाराप्रवाह NHibernate का उपयोग कर एक डेटाबेस के इस बाहर कॉपी और अन्य पर सहेजें या मैं अन्य विकल्पों को देखने की आवश्यकता होगी के लिए किसी भी अच्छा तरीका है?

इन प्रसंस्करण के लिए मेरे सामान्य पाश है: एक से दूसरे में और कुछ संस्थाओं के लिए

IList<Entities.Access.Revision> result; 
IList<int> recordIds = aSession.Query<Entities.Access.Revision>().Select(x => x.Id).ToList<int>(); 

foreach (int recordId in recordIds) 
{ 
    result = aSession.Query<Entities.Access.Revision>().Where(x => x.Id == recordId).ToList<Entities.Access.Revision>(); 
    Save(sqlDb, result); 
} 

सहेजें समारोह सिर्फ प्रतियां गुण डेटा में हेरफेर करने के लिए या डेटा की समस्याओं से संबंधित उपयोगकर्ता के लिए प्रतिक्रिया देने के लिए किया जाता है। मैं दोनों डेटाबेस के लिए स्टेटलेस सत्र का उपयोग कर रहा हूँ।

-

आगे वस्तुओं उस पर फांसी प्रतीत होता है परीक्षण से 60-70mb के बारे में कर रहे हैं। मैं वर्तमान में GetBytes का उपयोग कर OleDbDataReader के साथ डेटा को हथियाने का परीक्षण कर रहा हूं।

-

अद्यतन (नवम्बर 24): मैं अभी तक इस NHibernate के साथ काम करने के लिए पाने के लिए एक रास्ता खोजने के लिए है। मुझे यह नियमित डीबी कमांड ऑब्जेक्ट्स के साथ काम मिल गया। मैंने उस फंक्शन के लिए कोड डाला है जिसे मैंने नीचे दिया है जो किसी को भी जिज्ञासा देता है। यह मेरे डेटाबेस कनवर्टर से कोड है इसलिए 'ए' के ​​साथ prefixed ऑब्जेक्ट्स डेटाबेस डेटाबेस ऑब्जेक्ट्स हैं और 's' sql हैं।

public void MigrateBinaryField(int id, string tableName, string fieldName) 
{ 
    var aCmd = new OleDbCommand(String.Format(@"SELECT ID, {0} FROM {1} WHERE ID = {2}", fieldName, tableName, id), aConn); 

    using (var reader = aCmd.ExecuteReader(System.Data.CommandBehavior.SequentialAccess)) 
    { 
     while (reader.Read()) 
     { 
      if (reader[fieldName] == DBNull.Value) 
       return; 

      long read = 0; 
      long offset = 0; 

      // Can't .WRITE a NULL column so need to set an initial value 
      var sCmd = new SqlCommand(string.Format(@"UPDATE {0} SET {1} = @data WHERE OldId = @OldId", tableName, fieldName), sConn); 
      sCmd.Parameters.AddWithValue("@data", new byte[0]); 
      sCmd.Parameters.AddWithValue("@OldId", id); 
      sCmd.ExecuteNonQuery(); 

      // Incrementally store binary field to avoid OutOfMemoryException from having entire field loaded in memory 
      sCmd = new SqlCommand(string.Format(@"UPDATE {0} SET {1}.WRITE(@data, @offset, @len) WHERE OldId = @OldId", tableName, fieldName), sConn); 
      while ((read = reader.GetBytes(reader.GetOrdinal(fieldName), offset, buffer, 0, buffer.Length)) > 0) 
      { 
       sCmd.Parameters.Clear(); 
       sCmd.Parameters.AddWithValue("@data", buffer); 
       sCmd.Parameters.AddWithValue("@offset", offset); 
       sCmd.Parameters.AddWithValue("@len", read); 
       sCmd.Parameters.AddWithValue("@OldId", id); 

       sCmd.ExecuteNonQuery(); 

       offset += read; 
      }      
     } 
    } 
} 
+1

हेव आपने यह कोशिश की? https://github.com/bittercoder/Lob – Najera

+0

@ नजरा मैंने इसे एक शॉट दिया और काम नहीं किया। मैं विनिर्देशों को याद नहीं कर सकता लेकिन लगता है कि अभी भी स्मृति अपवादों से बाहर निकलना याद है। हालांकि यह थोड़ी देर हो गया है, हालांकि उस पर 100% नहीं है। –

+0

क्या आप हमें मैपिंग के साथ प्रदान कर सकते हैं? – TedOnTheNet

उत्तर

0

ऐसा लगता है कि मैंने अन्य ढांचे के शीर्ष पर .NET का उपयोग करने के साथ देखा है।

NHibernate के नीचे ADO.NET के नीचे मूल डेटाबेस ड्राइवर (दो "नीचे" जानबूझकर हैं) को एक पिन किए गए गंतव्य मेमोरी ब्लॉक की आवश्यकता होगी जिसे ड्राइवर में भरने के दौरान स्मृति में स्थानांतरित नहीं किया जा सकता है। के बाद से नेट कचरा कलेक्टर बेतरतीब ढंग से आदेश ढेर संकुचित करने के लिए में एक अलग थ्रेड पर स्मृति के ब्लॉक स्थानांतरित कर सकते हैं, NHibernate के अंतर्निहित नेट डेटाबेस परत डेटा, जो प्रभावी रूप से स्मृति की मात्रा दोगुना हो जाता है प्राप्त करने के लिए एक गैर-प्रबंधित स्मृति ब्लॉक बनाने के लिए है एक रिकॉर्ड लोड करने के लिए आवश्यक है।

इसके अलावा, मैं यह अगले बिंदु सत्यापित नहीं किया है, लेकिन चूंकि यह रिलेशनल डेटाबेस क्वेरी आपरेशन के कुछ नजरअंदाज NHibernate, रिकॉर्ड के ब्लॉक कैश करने के लिए प्रयास करना चाहिए। यह NHibernate कम डेटाबेस अनुरोध है, जो छोटे रिकॉर्ड आकार के लिए इष्टतम है बनाने के लिए अनुमति देता है, लेकिन (कई धब्बे सहित) कई रिकॉर्ड की आवश्यकता है एक समय में स्मृति में फिट करने के लिए।

एक संकल्प की ओर पहला कदम के रूप में, सुनिश्चित करें कि प्रक्रिया वास्तव में मशीन को स्मृति से बाहर चला रही है (या यदि यह 32-बिट है, तो सुनिश्चित करें कि यह 2 जीबी सीमा को मार रहा है)। यदि ऐसा है, तो बेसलाइन निर्धारित करने का प्रयास करें - यदि यह विभिन्न प्रकार के ब्लॉब आकारों के साथ रिकॉर्ड प्रोसेस कर रहा है, तो यह न्यूनतम और अधिकतम मेमोरी का उपयोग करता है? उस से, आप अनुमान लगा सकते हैं कि उस बड़े रिकॉर्ड के लिए कितनी मेमोरी की आवश्यकता होगी (या कैश ब्लॉक जिसमें रिकॉर्ड है!)

64-बिट और अधिक भौतिक स्मृति एक ब्रूट-फोर्स समाधान हो सकता है, यदि आप ' पहले से ही 64-बिट चल रहा है, और यदि बड़ा हार्डवेयर भी एक विकल्प है।

एक और संभावित समाधान यह जांचना है कि क्या NHibernate में कॉन्फ़िगर करने योग्य सेटिंग्स या गुण हैं जो डेटा को कैश करता है। उदाहरण के लिए, जांचें कि क्या आप एक ऐसी संपत्ति सेट कर सकते हैं जो एक समय में कितने रिकॉर्ड लोड हो जाएं, या इसे अपने कैश को बाइट्स में किसी निश्चित आकार में सीमित करने के लिए कहें।

ब्लॉब्स के लिए अपने ADO.NET कोड का उपयोग करने के लिए एक और अधिक कुशल समाधान है; यह सबसे अच्छा समाधान हो सकता है, खासकर अगर आप इस विशेष 60-70 एमबी ब्लॉब से भी बड़े ब्लब्स की अपेक्षा करते हैं। एमएस एक्सेस आम तौर पर एकाधिक रीड-ओनली कनेक्शन की अनुमति देगा, इसलिए यह तब तक काम करना चाहिए जब तक NHHernate अन्य कनेक्शन को ब्लॉक करने के लिए डेटाबेस सेट नहीं करता है।

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