Linq: सशर्त रूप से जहाँ क्लॉज़ की शर्तों को जोड़ना


103

मेरे पास इस तरह से एक प्रश्न है

(from u in DataContext.Users
       where u.Division == strUserDiv 
       && u.Age > 18
       && u.Height > strHeightinFeet  
       select new DTO_UserMaster
       {
         Prop1 = u.Name,
       }).ToList();

मैं इस क्वेरी को चलाने की विधि को प्रदान की गई उन शर्तों के आधार पर उम्र, ऊंचाई जैसी विभिन्न स्थितियों को जोड़ना चाहता हूं। सभी स्थितियों में उपयोगकर्ता प्रभाग शामिल होगा। अगर उम्र की आपूर्ति की गई थी तो मैं इसे क्वेरी में जोड़ना चाहता हूं। इसी तरह, अगर ऊंचाई प्रदान की गई थी, तो मैं उसे भी जोड़ना चाहता हूं।

यदि यह एसक्यूएल प्रश्नों का उपयोग करके किया जाना था, तो मैंने स्ट्रिंग बिल्डर का उपयोग किया होगा ताकि उन्हें मुख्य स्ट्रॉसिक क्वेरी से जोड़ा जा सके। लेकिन यहाँ Linq में मैं केवल IF शर्त का उपयोग करने के बारे में सोच सकता हूं, जहां मैं एक ही क्वेरी तीन बार लिखूंगा, जिसमें प्रत्येक IF ब्लॉक में एक अतिरिक्त शर्त होगी। क्या ऐसा करने के लिए इससे अच्छा तरीका है?

जवाबों:


182

यदि आप ToList()DTO प्रकार पर कॉल नहीं करते हैं और आपका अंतिम मानचित्रण करते हैं, तो आप Whereक्लॉस को जोड़ सकते हैं जैसे आप जाते हैं, और अंत में परिणाम बनाएँ:

var query = from u in DataContext.Users
   where u.Division == strUserDiv 
   && u.Age > 18
   && u.Height > strHeightinFeet
   select u;

if (useAge)
   query = query.Where(u => u.Age > age);

if (useHeight)
   query = query.Where(u => u.Height > strHeightinFeet);

// Build the results at the end
var results = query.Select(u => new DTO_UserMaster
   {
     Prop1 = u.Name,
   }).ToList();

इसके बाद भी डेटाबेस को केवल एक ही कॉल मिलेगा, जो एक पास में क्वेरी लिखने के समान प्रभावी होगा।


1
क्या मुझे "var query = .." स्टेटमेंट में सभी कहाँ स्थितियाँ डालने की आवश्यकता है?
user20358

4
बाद की स्थितियां या तो या के रूप में एकत्र की जाती हैं?
वि .१००

4
@ vi100 वे अतिरिक्त फ़िल्टर होंगे, इसलिए
रीड कोपसे

सादगी के लिए शुक्रिया! मैं 20+ लाइन के
लिनेक

मुझे यह त्रुटि क्यों हो रही हैLINQ to Entities does not recognize the method 'System.String get_Item(System.String)' method, and this method cannot be translated into a store expression.
अली उमर

19

मैं आमतौर पर मैथिंग चैनिंग का उपयोग करता हूं लेकिन एक ही समस्या है। और यहाँ विस्तार मैं उपयोग है

public static IQueryable<T> ConditionalWhere<T>(
        this IQueryable<T> source, 
        Func<bool> condition,
        Expression<Func<T, bool>> predicate)
    {
        if (condition())
        {
            return source.Where(predicate);
        }

        return source;
    }

यह चेन ब्रेक से बचने में मदद करता है। साथ ही समान ConditionalOrderByऔर ConditionalOrderByDescendingसहायक होते हैं।


सहायक, लेकिन क्या आप इसका उपयोग करने में कैसा लगेगा इसका एक उदाहरण जोड़ेंगे।
Suncat2000

1
यह इस प्रकार होना चाहिए: var फल = प्रतीक्षा db.Fruit .ConditionalWhere () => रंग! = Null, f => f.Color == रंग) .ConditionalWhere () () => परिपक्व! Null, f => f .Ripe == ripe) .ToListAsync ();
यूरी ग्रानोवस्की

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

18

एक विकल्प।

bool? age = null

(from u in DataContext.Users
           where u.Division == strUserDiv 
           && (age == null || (age != null && u.Age > age.Value))
           && u.Height > strHeightinFeet  
           select new DTO_UserMaster
           {
             Prop1 = u.Name,
           }).ToList();

या आप linq के लिए विधि सिंटैक्स पर जा सकते हैं और जहाँ क्लॉज़ के लिए अभिव्यक्ति संलग्न करने के लिए स्थितियों का उपयोग कर सकते हैं।


3

बस मैं इसे अपने क्लॉज़ के रूप में उपयोग कर रहा हूँ

    public IList<ent_para> getList(ent_para para){
     db.table1.Where(w=>(para.abc!=""?w.para==para.abc:true==true) && (para.xyz!=""?w.xyz==para.xyz:true==true)).ToList();
}

3

कुछ कंडोम के आधार पर, जहां शर्त जोड़ें ...

from u in DataContext.Users
where u.Division == strUserDiv 
&& u.Age != null ? u.Age > 18 : 1== 1
&& u.Height != null ? u.Height > 18 : 1== 1
&& u.Height != null ? u.Height > 18 : 1== 1
 select new DTO_UserMaster
       {
         Prop1 = u.Name,
       }).ToList();

2

यहाँ एक समान काम करने के लिए मेरा कोड है। यह मेरी WCF SOAP वेब सेवा एपीआई पर एक विधि है।

    public FruitListResponse GetFruits(string color, bool? ripe)
    {
        try
        {
            FruitContext db = new FruitContext();
            var query = db.Fruits.Select(f => f);
            if (color != null)
            {
                query = query.Where(f => f.Color == color);
            }
            if (ripe != null)
            {
                query = query.Where(f => f.Ripe == ripe);
            }
            return new FruitListResponse
            {
                Result = query.Select(f => new Fruit { Id = f.FruitId, Name = f.Name }).ToList()
            };
        }
        catch (Exception e)
        {
            return new FruitListResponse { ErrorMessage = e.Message };
        }
    }

आधार क्वेरी Select(f => f)जिसका अर्थ है मूल रूप से सब कुछ, और Whereखंड वैकल्पिक रूप से इसके साथ जुड़े हुए हैं। फाइनल Selectवैकल्पिक है। मैं डेटाबेस पंक्तियों की वस्तुओं को "फल" वस्तुओं में बदलने के लिए उपयोग करता हूं।


0

निम्नलिखित पैरामीटर मानकर,

Int? Age = 18;

बस का उपयोग कर &&और ||सशर्त ऑपरेटरों हम एक और संस्करण हो सकता है।

(from u in DataContext.Users
where u.Division == strUserDiv 
    && (Age == null || u.Age > Age)
    && (Param1 == null || u.param1 == Param1)
    && u.Height > strHeightinFeet
select new DTO_UserMaster
{
    Prop1 = u.Name,
}).ToList();

Param1 की तरह आप खोज स्थिति के लिए किसी भी संख्या में पैरामीटर जोड़ सकते हैं।


0

मैं अभी कुछ और तलाश कर रहा था, लेकिन मैंने सोचा कि मैं लैम्बडा संस्करण में फेंक दूंगा।

सबसे पहले, मैं डेटा स्तर में मापदंडों को पारित करने के लिए इस तरह एक वर्ग बनाऊंगा:

   public class SearchParameters() {
       public int? Age {get; set;}
       public string Division {get;set;}
       etc
    }

फिर, मेरी डेटा लेयर में, कुछ इस तरह:

public IQueryable<User> SearchUsers(SearchParameters params) 
{
    var query = Context.Users;
    if (params.Age.HasValue)
    {
         query = query.Where(u => u.Age == params.Age.Value);
    }
    if (!string.IsNullOrEmpty(params.Division)
    {
        query = query.Where(u => u.Division == params.Division);
    }
    etc
    return query;
}

जहाँ आप क्वेरी करते हैं, आप पर निर्भर है। ऐप और डेटा के बीच एक परत हो सकती है जो db-agnostic को डीबी-विशिष्ट अभ्यावेदन को परिवर्तित करती है (हो सकता है कि आप कई अतिरिक्त डेटा क्वेरी करें)। इस परत को इन स्रोतों से कई प्रकार की क्वेरी मिल सकती हैं और उदाहरण के लिए, उन्हें एक सामान्य POCO प्रतिनिधित्व में मैप कर सकते हैं।


ओह, मैंने जॉन हेन्केल का जवाब नहीं देखा। एक ही विचार।
स्कॉट पीटरसन

0

बस यहाँ ऊपर दिए गए उत्तर को जोड़ने के लिए , यदि आप किसी ज्वाइन पर एक डायनामिक खोज कर रहे हैं, तो प्रारंभिक लिनेक क्वेरी में दोनों तालिकाओं (t1, t2) के साथ एक नई वस्तु को वापस करने पर विचार करें ताकि आप सशर्त करने के लिए उन्हें व्यक्तिगत रूप से एक्सेस कर सकें। खोज।

var query = from t1 in _context.Table1
            join t2 in _context.Table2 on t1.Table1Id equals t2.Table1IdId
            select new { t1, t2 };

        if (!string.IsNullOrEmpty(searchProperty1))
        {
            query = query.Where(collection => collection.t1.TableColumn == searchProperty1);
        }
        if (!string.IsNullOrEmpty(searchProperty2))
        {
            query = query.Where(collection => collection.t2.TableColumn == searchProperty2);
        }
        ....etc.

मुझे जवाब मिला कि मैं दो तालिकाओं के साथ जुड़ने के संबंध में यहाँ देख रहा था और दोनों में से किसी एक स्तंभ पर विशिष्ट कॉलमों को क्वेरी कर रहा था

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.