2009-01-29 14 views
33

मेरे एकीकरण परीक्षण को स्वतंत्र रखने के लिए मैं सभी पुराने डेटा को हटा देता हूं और प्रत्येक परीक्षण से पहले नया परीक्षण डेटा डालता हूं। क्या सभी संस्थाओं के लिए पूछताछ करने और उन्हें एक-एक करके हटाने से बेहतर करने का कोई बेहतर तरीका है?NHibernate का उपयोग कर तालिका में सभी पंक्तियों को हटाने का सबसे अच्छा तरीका?

मैंने एक संग्रहित प्रो लिखने पर विचार किया है जो "tablename से हटाता है;" प्रत्येक तालिका के लिए जिसे साफ़ किया जाना है। यह काफी तेज़ होना चाहिए, लेकिन एनएच के माध्यम से एसक्यूएल प्रश्न पूछने या एसपी को कॉल करने के बिना ऐसा करना अच्छा होगा।

मैं वेनिला एनएचबेर्नेट और लिंक से NHibernate का उपयोग कर रहा हूं। मैं बेलीव कैसल एक्टिव रिकॉर्ड में Foo.DeleteAll() की तरह कुछ है, लेकिन मैं इस प्रोजेक्ट के लिए सक्रिय रिकॉर्ड का उपयोग नहीं करना चाहता हूं।

कोई भी विचार?

धन्यवाद/एरिक

अद्यतन:

चूंकि यह प्रश्न पूछा गया था और उत्तर दिया, प्रगति NHibernate टीम द्वारा बनाया गया है। जैसा कि आयुन्डे this blog post में बताते हैं, अब आप एनएमबीर्नेट को किसी भी संस्था को लाने के बिना सीधे डीएमएल प्रश्न निष्पादित कर सकते हैं।

सभी फू वस्तुओं आप इस तरह कर सकता है हटाने के लिए:

using (ISession session = ...) 
using (ITransaction transaction = session.BeginTransaction()) 
{ 
    session.CreateQuery("delete Foo f").ExecuteUpdate(); 

    transaction.Commit(); 
} 

इस क्वेरी निम्नलिखित एसक्यूएल उत्पन्न होगा:

delete from Foo 

जो किसी प्रकार से पहले और उसके बाद संस्थाओं को लाते समय की तुलना में काफी तेजी से होने के लिए उन्हें हटाना हालांकि सावधान रहें, क्योंकि इन तरह के प्रश्न स्तर 1 कैश को प्रभावित नहीं करते हैं।

+2

यदि आप SQL सर्वर का उपयोग कर रहे हैं तो यह 'TRUNCATE तालिका Foo' निष्पादित करने के लिए बहुत अधिक कुशल है, क्योंकि यह न्यूनतम रूप से लॉग इन ऑपरेशन है। 'Foo से हटाएं' निष्पादित करना; पुनर्प्राप्ति उद्देश्यों के लिए सभी हटाए गए लॉग; बड़ी टेबल पर इसे महत्वपूर्ण डिस्क/समय की आवश्यकता होती है। –

+3

ट्रंकेट टेबल लगभग विदेशी उपलब्ध होने पर लगभग कभी उपलब्ध नहीं होता है। –

उत्तर

32

मेरी UnitTests की टियरडाउन में, मैं ज्यादातर ऐसा करते हैं:

using(ISession s = ...) 
{ 
    s.Delete ("from Object o"); 
    s.Flush(); 
} 

यह सभी संस्थाओं को नष्ट करना चाहिए। आप एक विशेष इकाई के सभी उदाहरणों को नष्ट करना चाहते हैं, तो आप ऐसा कर सकते हैं:

using(ISession s = ....) 
{ 
    s.Delete ("from MyEntityName e"); 
    s.Flush(); 
} 

Offcourse, वहाँ इस विधि के साथ एक दोष है, और है कि NHibernate पहली बार उन्हें हटाने से पहले इकाइयां नहीं लाई जाएगा।

+0

ओह, मैंने पूरी तरह से याद किया था कि आप सत्र में एक क्वेरी पास कर सकते हैं। हटाएं()। धन्यवाद! –

+7

बीटीडब्लू: बड़ी टेबल पर यह घातक धीमी है –

+0

इनडेड, यह मेरी कमी का उल्लेख है। –

10

मैं धाराप्रवाह NHibernate विशेषताओं का उपयोग तो मैं कोड एक छोटे से आदेश तालिका नाम कट्टर नहीं में संशोधित

private static void CleanUpTable<T>(ISessionFactory sessionFactory) 
{ 
    var metadata = sessionFactory.GetClassMetadata(typeof(T)) as NHibernate.Persister.Entity.AbstractEntityPersister; 
    string table = metadata.TableName; 

    using (ISession session = sessionFactory.OpenSession()) 
    { 
     using (var transaction = session.BeginTransaction()) 
     { 
      string deleteAll = string.Format("DELETE FROM \"{0}\"", table); 
      session.CreateSQLQuery(deleteAll).ExecuteUpdate(); 

      transaction.Commit(); 
     } 
    } 
} 

उपयोग

CleanUpTable<Person>(sessionFactory); 
+0

मैंने इस सवाल को संपादित करने के खिलाफ फैसला किया है क्योंकि "कट्टर" वास्तव में "हार्डकोड" से कहीं ज्यादा बेहतर लगता है, भले ही यह बाद वाला था। –

1
NHibernate 5.0 के साथ

आप अब बस कर सकते हैं:

session.Query<Foo>().Delete(); 

प्रलेखन:

// 
    // Summary: 
    //  Delete all entities selected by the specified query. The delete operation is 
    //  performed in the database without reading the entities out of it. 
    // 
    // Parameters: 
    // source: 
    //  The query matching the entities to delete. 
    // 
    // Type parameters: 
    // TSource: 
    //  The type of the elements of source. 
    // 
    // Returns: 
    //  The number of deleted entities. 
    public static int Delete<TSource>(this IQueryable<TSource> source);