Linq SQL के लिए कैसे करें "जहां" [कॉलम] में (मूल्यों की सूची) "


101

मेरे पास एक फ़ंक्शन है जहां मुझे आईडी की एक सूची मिलती है, और मुझे विवरण के साथ मेल खाते एक सूची को वापस करने की आवश्यकता है जो आईडी के साथ जुड़ा हुआ है। उदाहरण के लिए:

public class CodeData
{
    string CodeId {get; set;}
    string Description {get; set;}
}

public List<CodeData> GetCodeDescriptionList(List<string> codeIDs)
    //Given the list of institution codes, return a list of CodeData
    //having the given CodeIds
}

इसलिए यदि मैं इसके लिए खुद ही sql बना रहा था, तो मैं बस निम्नलिखित की तरह कुछ करूँगा (जहाँ खंड में कोड मान में सभी मान शामिल हैं):

Select CodeId, Description FROM CodeTable WHERE CodeId IN ('1a','2b','3')

Linq में Sql करने के लिए मैं "IN" खंड के बराबर नहीं मिल सकता है। मैंने अब तक जो सबसे अच्छा पाया है (जो काम नहीं करता है) है:

 var foo = from codeData in channel.AsQueryable<CodeData>()
           where codeData.CodeId == "1" || codeData.CodeId == "2"
           select codeData;

समस्या यह है कि, मैं गतिशील रूप से linq से sql के लिए "या" खंड की सूची उत्पन्न नहीं कर सकता, क्योंकि वे संकलन समय पर सेट हैं।

लाइनक को Sql का उपयोग करके मूल्यों की एक गतिशील सूची में स्तंभ की जांच करने वाले एक खंड को कैसे पूरा किया जाता है?

जवाबों:


159

उपयोग

where list.Contains(item.Property)

या आपके मामले में:

var foo = from codeData in channel.AsQueryable<CodeData>()
          where codeIDs.Contains(codeData.CodeId)
          select codeData;

लेकिन आप डॉट नोटेशन में भी ऐसा कर सकते हैं:

var foo = channel.AsQueryable<CodeData>()
                 .Where(codeData => codeIDs.Contains(codeData.CodeId));

CodeId के मामले में उपयोग कैसे करें?
किरण सोलकर

2
@KiranSolkar: तो संभवतः codeIDsएक होगा List<int>, और सब ठीक हो जाएगा।
जॉन स्कीट

@JonSkeet क्या मामला संवेदनशील नहीं है? यदि codeIDs अपरकेस स्ट्रिंग्स की सूची है और codeData.codeId एक लोअरकेस स्ट्रिंग है, तो यह विफल हो जाएगा।
पर्सजैक

@PersyJack: केस-असंवेदनशील होने के बारे में सवाल में कुछ भी नहीं था। जैसा कि होगा या नहीं होगा, मुझे याद नहीं है कि LINQ SQL डिफ़ॉल्ट रूप से केस-सेंसिटिविटी को लागू करता है या dbb को इसे नियंत्रित करता है।
जॉन स्कीट

1
@PersyJack LINQ to SQL T-SQL क्वेरी उत्पन्न करता है, जो तब केस-सेंसिटिविटी के लिए डेटाबेस सेटिंग्स का उपयोग करके SQL सर्वर पर चलता है। हालाँकि, यदि कोई सावधान नहीं है, और क्वेरी परिणामों को उत्प्रेरित करता है, LINQ को इन-मेमोरी ऑब्जेक्ट्स में लागू करने से पहले, वे बेमेल केस-सेंसिटिविटी के परिणाम भुगत सकते हैं।
ज़ेरेफेथ

26

आप यह भी उपयोग कर सकते हैं:

List<int> codes = new List<int>();

codes.add(1);
codes.add(2);

var foo = from codeData in channel.AsQueryable<CodeData>()
          where codes.Any(code => codeData.CodeID.Equals(code))
          select codeData;

1
IQToolkit के हमारे कार्यान्वयन का समर्थन नहीं करने के बाद से मुझे इसका इस्तेमाल करना पड़ा। कॉन्टेक्ट्स ()
डीजे वैन

1

मैं जॉन स्कीट के जवाब में विधि का उपयोग कर रहा था, लेकिन एक और मेरे साथ हुआ ConcatConcatविधि सीमित परीक्षण में थोड़ा बेहतर प्रदर्शन किया है, लेकिन यह एक परेशानी है और मैं शायद सिर्फ साथ रह सकते हैं Contains, या हो सकता है मैं मेरे लिए यह करने के लिए एक सहायक विधि लिखेंगे। किसी भी तरह से, यहाँ किसी भी अन्य विकल्प अगर कोई दिलचस्पी है:

प्रक्रिया

// Given an array of id's
var ids = new Guid[] { ... };

// and a DataContext
var dc = new MyDataContext();

// start the queryable
var query = (
    from thing in dc.Things
    where thing.Id == ids[ 0 ]
    select thing 
);

// then, for each other id
for( var i = 1; i < ids.Count(); i++ ) {
    // select that thing and concat to queryable
    query.Concat(
        from thing in dc.Things
        where thing.Id == ids[ i ]
        select thing
    );
}

प्रदर्शन का परीक्षण

यह दूरस्थ रूप से वैज्ञानिक नहीं था। मुझे लगता है कि आपके डेटाबेस की संरचना और सूची में शामिल आईडी की संख्या का महत्वपूर्ण प्रभाव पड़ेगा।

मैंने एक परीक्षण स्थापित किया जहां मैंने प्रत्येक में 100 परीक्षण किए Concatऔर Containsजहां प्रत्येक परीक्षण में प्राथमिक कुंजियों की यादृच्छिक सूची द्वारा निर्दिष्ट 25 पंक्तियों का चयन करना शामिल था। मैंने इसे लगभग एक दर्जन बार चलाया है, और अधिकांश बार Concatविधि 5 से 10% तेजी से निकलती है, हालांकि एक बार Containsविधि सिर्फ एक स्मिडजेन द्वारा जीती जाती है।


0
 var filterTransNos = (from so in db.SalesOrderDetails
                    where  ItemDescription.Contains(ItemDescription)
                            select new { so.TransNo }).AsEnumerable();    


listreceipt = listreceipt.Where(p => filterTransNos.Any(p2 => p2.TransNo == p.TransNo)).ToList();

-1

यहाँ हैशसेट का उपयोग करके मैं इसे कैसे करता हूँ

        HashSet<String> hs = new HashSet<string>(new String[] { "Pluto", "Earth", "Neptune" });
        String[] arr =
        {
            "Pluto",
            "Earth",
            "Neptune",
            "Jupiter",
            "Saturn",
            "Mercury",
            "Pluto",
            "Earth",
            "Neptune",
            "Jupiter",
            "Saturn",
            "Mercury",
            // etc.
        };
        ICollection<String> coll = arr;

        String[] arrStrFiltered = coll.Where(str => hs.Contains(str)).ToArray();

हैशसेट मूल रूप से लगभग O (1) है, इसलिए आपकी जटिलता O (n) बनी हुई है।


यह LINQ-to-SQL के बारे में है। ऐसे LINQ-to-Objects विचार लागू नहीं होते हैं।
गर्ट अर्नोल्ड

ICQlection एक LINQ-SQL से भी आ सकता है, यह एक सामान्य तरीका है
MG

सवाल यह है कि एक अभिव्यक्ति का निर्माण कैसे किया जाए जो सही एसक्यूएल में अनुवाद हो। इसका स्थानीय संग्रह की खोज करने से कोई लेना-देना नहीं है। आपका जवाब केवल भविष्य के पाठकों को भ्रमित करेगा जो इस भेद के बारे में नहीं जानते हैं।
गर्ट अर्नोल्ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.