2009-12-08 13 views
7

निम्नलिखित LINQ बयान:यह LINQ-to-SQL क्वेरी को NotSupportedException क्यों मिलता है?

System.NotSupportedException:: स्थानीय अनुक्रम क्वेरी ऑपरेटरों को छोड़कर की कार्यान्वयन SQL करने के लिए LINQ में नहीं किया जा सकता

public override List<Item> SearchListWithSearchPhrase(string searchPhrase) 
{ 
    List<string> searchTerms = StringHelpers.GetSearchTerms(searchPhrase); 

    using (var db = Datasource.GetContext()) 
    { 
     return (from t in db.Tasks 
       where searchTerms.All(term => 
        t.Title.ToUpper().Contains(term.ToUpper()) && 
        t.Description.ToUpper().Contains(term.ToUpper())) 
       select t).Cast<Item>().ToList(); 
    } 
} 

मुझे इस त्रुटि देता है कंटेनर() ऑपरेटर।

इसके चारों ओर देख रहे हैं लगता है मेरी ही एकमात्र विकल्प एक सामान्य सूची में सभी मेरे आइटम पहले प्राप्त करने के लिए है, तो उस पर एक LINQ क्वेरी करना है।

या क्या त्रुटि से बचने के लिए उपरोक्त LINQ-to-SQL कथन को फिर से भरने का एक चालाक तरीका है?

उत्तर:

धन्यवाद रैंडी, अपने विचार मुझे मदद की निम्नलिखित समाधान का निर्माण करने के लिए। यह सुरुचिपूर्ण नहीं है लेकिन यह समस्या हल करता है और चूंकि यह कोड उत्पन्न होगा, मैं उदाहरण के लिए संभाल सकता हूं बिना किसी अतिरिक्त काम के 20 खोज शब्द:

public override List<Item> SearchListWithSearchPhrase(string searchPhrase) 
{ 
    List<string> searchTerms = StringHelpers.GetSearchTerms(searchPhrase); 

    using (var db = Datasource.GetContext()) 
    { 

     switch (searchTerms.Count()) 
     { 
      case 1: 
       return (db.Tasks 
        .Where(t => 
         t.Title.Contains(searchTerms[0]) 
         || t.Description.Contains(searchTerms[0]) 
         ) 
        .Select(t => t)).Cast<Item>().ToList(); 
      case 2: 
       return (db.Tasks 
        .Where(t => 
         (t.Title.Contains(searchTerms[0]) 
         || t.Description.Contains(searchTerms[0])) 
         && 
         (t.Title.Contains(searchTerms[1]) 
         || t.Description.Contains(searchTerms[1])) 
         ) 
        .Select(t => t)).Cast<Item>().ToList(); 
      case 3: 
       return (db.Tasks 
        .Where(t => 
         (t.Title.Contains(searchTerms[0]) 
         || t.Description.Contains(searchTerms[0])) 
         && 
         (t.Title.Contains(searchTerms[1]) 
         || t.Description.Contains(searchTerms[1])) 
         && 
         (t.Title.Contains(searchTerms[2]) 
         || t.Description.Contains(searchTerms[2])) 
         ) 
        .Select(t => t)).Cast<Item>().ToList(); 
      default: 
       return null; 
     } 
    } 
} 
+0

ध्यान दें कि यह "लागू नहीं किया गया" त्रुटि नहीं है, यह एक "स्थानीय अनुक्रम का उपयोग नहीं किया जा सकता" त्रुटि है। – Lucas

+0

धन्यवाद, –

+0

तय किया गया है कि मुझे यकीन नहीं है कि मैं इसे सही तरीके से पढ़ रहा हूं, यह बहुत सारे ब्रैकेट हैं लेकिन मुझे एक अच्छी तरह से गठित क्लॉज नहीं दिख रहा है। आपकी खोज Terms.All() तारों की एक सूची लौट रही है जो एक खंड नहीं बना है, इसलिए त्रुटि। – Lazarus

उत्तर

1

एड, मैं एक समान परिस्थिति में चला गया हूं। कोड नीचे है। कोड की महत्वपूर्ण पंक्ति वह जगह है जहां मैंने सदस्य सूची चर सेट किया है। देखें कि यह आपकी स्थिति फिट बैठता है या नहीं। क्षमा करें अगर स्वरूपण अच्छी तरह से बाहर नहीं आया था।

रैंडी

// Get all the members that have an ActiveDirectorySecurityId matching one in the list. 
IEnumerable<Member> members = database.Members 
    .Where(member => activeDirectoryIds.Contains(member.ActiveDirectorySecurityId)) 
    .Select(member => member); 

// This is necessary to avoid getting a "Queries with local collections are not supported" 
//error in the next query.  
memberList = members.ToList<Member>(); 

// Now get all the roles associated with the members retrieved in the first step. 
IEnumerable<Role> roles = from i in database.MemberRoles 
    where memberList.Contains(i.Member) 
    select i.Role; 
+0

क्षमा करें रैंडी लेकिन आप यहां बिंदु को याद करते हैं। – Lazarus

1

जब से तुम LINQ की मेज के साथ स्थानीय अनुक्रम शामिल नहीं हो सकते, एसक्यूएल में ऊपर क्वेरी का अनुवाद हो woluld एक ही रास्ता बनाने के लिए जहां के रूप में कई के रूप में वहाँ searchTerms सूची में तत्व हैं की स्थिति की तरह साथ खंड (एंड ऑपरेटरों के साथ मिलकर)। स्पष्ट रूप से linq स्वचालित रूप से ऐसा नहीं करता है और इसके बजाय एक अपवाद फेंकता है। लेकिन यह अनुक्रम के माध्यम से पुनरावृत्ति द्वारा मैन्युअल रूप से किया जा सकता है:

public override List<Item> SearchListWithSearchPhrase(string searchPhrase) 
{ 
    List<string> searchTerms = StringHelpers.GetSearchTerms(searchPhrase); 

    using (var db = Datasource.GetContext()) 
    { 
     IQueryable<Task> taskQuery = db.Tasks.AsQueryable(); 
     foreach(var term in searchTerms) 
     { 
       taskQuery = taskQuery.Where(t=>t.Title.ToUpper().Contains(term.ToUpper()) && t.Description.ToUpper().Contains(term.ToUpper()))    
     } 
     return taskQuery.ToList(); 
    } 
} 

मन कि क्वेरी अभी भी एक एसक्यूएल बयान के रूप में DBMS द्वारा निष्पादित किया जाता है। एकमात्र कमी यह है कि SearchTerms सूची लंबे समय तक नहीं होनी चाहिए - अन्यथा उत्पादित SQL कथन कुशल नहीं होगा।

+0

यह अच्छा लग रहा है, लेकिन मैं इसे काम नहीं कर सकता, मैं प्राप्त करता रहता हूं: ऊपरी फ़ंक्शन के तर्क 1 के लिए तर्क डेटा प्रकार टेक्स्ट अमान्य है। –

+0

यदि आपके डेटाबेस कॉलम शीर्षक और विवरण में टेक्स्ट टाइप किया गया है तो अधिकांश ऑपरेटरों जैसे CONTAINS ('like'), और शायद TOUPPER काम नहीं करेगा। टेक्स्ट कॉलम को पूर्ण पाठ खोज अनुक्रमणिका, और linq के बजाय संग्रहीत प्रक्रियाओं के साथ पूछताछ की जानी चाहिए। तो या तो एफटीएस का उपयोग करें (http: // msdn।microsoft.com/en-us/library/ms142571.aspx) या टेक्स्ट से NVARCHAR (MAX) में कॉलम बदलें। (मैं एसक्यूएल सर्वर के बारे में बात कर रहा हूँ) – PanJanek

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