2011-02-28 17 views
26

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

यदि यह साधारण ADO.NET थे, मैं स्पष्ट रूप से सिर्फ DbCommand.Cancel समारोह इस्तेमाल कर सकते हैं और इसके साथ किया जाना है, लेकिन हम अपने डेटा पहुँच के लिए EF4 उपयोग कर रहे हैं और वहाँ एक रद्द करने के लिए एक स्पष्ट तरीका हो प्रतीत नहीं होता है क्वेरी। इसके अतिरिक्त, प्रतिबिंबक में System.Data.Entity खोलना और EntityCommand.Cancel पर देखकर docs के बावजूद एक निराशाजनक खाली विधि निकाय दिखाता है, यह दावा करते हुए कि यह इसे प्रदाता कमांड के संबंधित Cancel फ़ंक्शन पर भेज देगा।

मैंने केवल मौजूदा क्वेरी को चलाने और नई खोज को निष्पादित करने के लिए एक नए संदर्भ को कताई करने के लिए विचार किया है (और केवल एक बार समाप्त होने के बाद मौजूदा क्वेरी का निपटान), लेकिन मुझे एक क्लाइंट के विचार को पसंद नहीं है खुले डेटाबेस कनेक्शन की एक भीड़ समानांतर क्वेरी चल रही है जब मैं केवल हालिया परिणामों के परिणामों में रूचि रखता हूं।

यह सब मुझे विश्वास करने के लिए प्रेरित कर रहा है कि डेटाबेस में भेजे जाने के बाद ईएफ क्वेरी को रद्द करने का कोई तरीका नहीं है, लेकिन मुझे उम्मीद है कि यहां कोई व्यक्ति कुछ अनदेखा कर सकता है जिसे मैंने अनदेखा कर दिया है।

टीएल/डीआर संस्करण: क्या वर्तमान में निष्पादित एक ईएफ 4 क्वेरी को रद्द करना संभव है?

+0

मैं MSDN मंच पर इस समस्या के बारे में सवाल पूछा है:: एक और दृष्टिकोण केवल वर्तमान क्वेरी को रोकने के लिए अंदर गणन है http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/ d5ea8036-73e5-4566-9407-fa7a6a5fca3c यह मूल प्रश्न जुड़ा हुआ है।उम्मीद है कि एमएस से कोई दूसरा समाधान प्रदान करेगा। –

उत्तर

12

ऐसा लगता है कि आपको ईएफ में कुछ बग मिला है, लेकिन जब आप इसे एमएस में रिपोर्ट करते हैं तो इसे दस्तावेज़ में बग के रूप में माना जाएगा। वैसे भी मुझे सीधे EntityCommand के साथ बातचीत करने का विचार पसंद नहीं है। यहाँ मेरी उदाहरण कैसे वर्तमान क्वेरी को मारने के लिए है:

var thread = new Thread((param) => 
    { 
     var currentString = param as string; 

     if (currentString == null) 
     { 
      // TODO OMG exception 
      throw new Exception(); 
     } 

     AdventureWorks2008R2Entities entities = null; 
     try // Don't use using because it can cause race condition 
     { 
      entities = new AdventureWorks2008R2Entities(); 

      ObjectQuery<Person> query = entities.People 
       .Include("Password") 
       .Include("PersonPhone") 
       .Include("EmailAddress") 
       .Include("BusinessEntity") 
       .Include("BusinessEntityContact"); 
      // Improves performance of readonly query where 
      // objects do not have to be tracked by context 
      // Edit: But it doesn't work for this query because of includes 
      // query.MergeOption = MergeOption.NoTracking; 

      foreach (var record in query 
       .Where(p => p.LastName.StartsWith(currentString))) 
      { 
       // TODO fill some buffer and invoke UI update 
      } 
     } 
     finally 
     { 
      if (entities != null) 
      { 
       entities.Dispose(); 
      } 
     } 
    }); 

thread.Start("P"); 
// Just for test 
Thread.Sleep(500); 
thread.Abort(); 

यह 30 यदि बाद मिनट के साथ अपने खेल का नतीजा तो यह शायद कुछ जो अंतिम समाधान के रूप में विचार किया जाना चाहिए नहीं है। मैं इसे कम से कम इस समाधान के कारण संभावित समस्याओं के साथ कुछ प्रतिक्रिया प्राप्त करने के लिए पोस्ट कर रहा हूं। मुख्य बिंदु निम्न हैं:

  • प्रसंग धागा अंदर नियंत्रित किया जाता है
  • परिणाम संदर्भ
  • द्वारा ट्रैक न होने वाला तुम्हें मार धागा क्वेरी समाप्त हो जाता है और संदर्भ निपटान किया जाता है (कनेक्शन जारी)
  • तुम्हें मार तो एक नया धागा शुरू करने से पहले धागा आपको अभी भी एक कनेक्शन का उपयोग करना चाहिए।

मैंने जांच की है कि क्वेरी प्रोफाइल प्रारंभ और SQL प्रोफाइलर में समाप्त हो गया है।

संपादित करें:

Btw।

public IEnumerable<T> ExecuteQuery<T>(IQueryable<T> query) 
{ 
    foreach (T record in query) 
    { 
     // Handle stop condition somehow 
     if (ShouldStop()) 
     { 
      // Once you close enumerator, query is terminated 
      yield break; 
     } 
     yield return record; 
    } 
} 
+0

दिलचस्प; स्पष्टीकरण के एक बिंदु के रूप में, मैं 'एंटीटी कमांड' के साथ बातचीत करने का सुझाव नहीं दे रहा था, लेकिन यह तथ्य था कि विधि निकाय खाली है, यह संभावना है कि यह भी संभव है कि यह एक उच्च स्तर पर भी संभव हो, स्लिम-टू-नो। यह एक दिलचस्प परिदृश्य है और अंत में काम कर सकता है, लेकिन अभी मुझे संभवतः परिवर्तन ट्रैकिंग की आवश्यकता है, इसलिए संदर्भ का निपटान ऐसा कुछ नहीं है जिसे मैं करने के लिए तैयार हूं। अगर मुझे कोई विकल्प नहीं मिल रहा है, तो मैं इसे स्वीकार करूंगा। –

+0

@Adam: ठीक है, मैं कल परिवर्तन ट्रैकिंग के साथ परिदृश्य के बारे में सोचूंगा क्योंकि इसके नए नतीजे हैं - भले ही आप क्वेरी को रद्द कर दें, भले ही सभी लोड किए गए उदाहरण पहले ही संदर्भ द्वारा ट्रैक किए जाएंगे। मेरा प्रारंभिक सुझाव प्रत्येक खोज के लिए नया संदर्भ है लेकिन मुझे इसके बारे में सोचना है। –

+0

मैं लोड होने के दौरान एक प्रश्न को रद्द करने से वास्तव में चिंतित नहीं हूं। यह आपके ऊपर के दृष्टिकोण के साथ आसानी से पर्याप्त रूप से हासिल किया गया है। मैं जो खोज रहा हूं वह * क्वेरी * चरण के दौरान इसे रद्द कर रहा है (जबकि यह सर्वर-साइड निष्पादित कर रहा है)। –

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