LINQ एक्सटेंशन के तरीकों के साथ मल्टीपल क्लॉजेज


79

मेरे पास एक LINQ क्वेरी है जो निम्नलिखित की तरह दिखती है:

DateTime today = DateTime.UtcNow;
var results = from order in context.Orders
              where ((order.OrderDate <= today) && (today <= order.OrderDate))
              select order;

मैं LINQ सीखने / समझने का प्रयास कर रहा हूँ। कुछ मामलों में, मुझे दो अतिरिक्त WHERE क्लॉज़ जोड़ने होंगे। ऐसा करने के प्रयास में, मैं उपयोग कर रहा हूं:

if (useAdditionalClauses)
{
  results = results.Where(o => o.OrderStatus == OrderStatus.Open)  // Now I'm stuck.
}

जैसा कि आप देख सकते हैं, मुझे पता है कि अतिरिक्त WHERE क्लॉज कैसे जोड़ा जाता है। लेकिन मैं एकाधिक कैसे जोड़ूं? उदाहरण के लिए, मैं जोड़ना चाहूंगा

WHERE o.OrderStatus == OrderStatus.Open AND o.CustomerID == customerID

मेरी पिछली क्वेरी के लिए। मैं इसे विस्तार विधियों का उपयोग कैसे करूं?

धन्यवाद!

जवाबों:


151

दो तरीके:

results = results.Where(o => (o.OrderStatus == OrderStatus.Open) &&
                             (o.CustomerID == customerID));

या:

results = results.Where(o => (o.OrderStatus == OrderStatus.Open))
                 .Where(o => (o.CustomerID == customerID));

मैं आमतौर पर बाद को पसंद करता हूं। लेकिन क्वेरी निष्पादन की जांच करने के लिए यह SQL सर्वर की रूपरेखा के लायक है और देखें कि कौन सा आपके डेटा के लिए बेहतर प्रदर्शन करता है (यदि कोई अंतर है)।

.Where()विधियों को चेंज करने के बारे में एक नोट : आप अपनी पसंद के सभी LINQ तरीकों को एक साथ चेन कर सकते हैं। .Where()डेटाबेस की तरह तरीके वास्तव में निष्पादित नहीं करते हैं (अभी तक)। वास्तविक परिणामों की गणना होने तक वे निष्पादन को स्थगित कर देते हैं (जैसे कि a .Count()या a .ToList())। इसलिए, जब आप एक साथ कई तरीकों (अधिक कॉल .Where(), शायद एक .OrderBy()या उस प्रभाव के लिए कुछ, आदि) को एक साथ चेन करते हैं, तो वे एक अभिव्यक्ति ट्री कहते हैं । यह संपूर्ण वृक्ष वह है जो डेटा स्रोत के विरुद्ध निष्पादित होता है जब समय इसका मूल्यांकन करता है।


2
मुझे लगता है कि मैं यह नहीं कर सका, मुझे पता नहीं है। आपने मुझे इतने स्पेगेटी कोड से बचाया।
ledgeJumper

धन्यवाद, इससे मुझे मदद मिली। लेकिन क्या यह भी संभव है कि मैं एक निश्चित चर के आधार पर किसी भी खंड को ट्रिगर करूंगा? @
दाविद

आप अंत में एक चुनिंदा खंड के साथ इसका उपयोग कर सकते हैं?

@ नई_कोडर: बिल्कुल। .Where () खंड रिटर्न प्रकार नहीं बदलता है।
डेविड

इसका अजीब इसलिए है क्योंकि जब मैं ऐसा करता हूं: सूची <string> पाथ्स = db.ClientStatement_Inventor .Where (x => (x.statementYear == yea))। कहाँ (x => (x .statementMonth == mon)) .Select () c => c.statementPath) .ToList (); यह काम नहीं करता है। लेकिन अगर मेरे पास केवल 1 है जहां यह खंड मेरे डेटाबेस पर सवाल उठाता है।

24

आप उन्हें जारी रख सकते हैं जैसे आपने किया है।

results = results.Where (o => o.OrderStatus == OrderStatus.Open);
results = results.Where (o => o.InvoicePaid);

यह एक का प्रतिनिधित्व करता है।


आप - और अन्य - मुझे भी इसे पीटते हैं, लेकिन यह शायद इसे करने का सबसे पठनीय तरीका है।
Schroedingers बिल्ली

5
दोहराया जहां क्लॉस को क्वेरी में "और" ऑपरेटर के बीच में जोड़ा जाता है।
लिंकरो

यह शायद 'सबसे साफ' समाधान नहीं है, लेकिन मेरे मामले में यह एकमात्र ऐसा काम है जो अब तक काम करता है। मुझे UI में चयनों के आधार पर 'जहाँ' क्लॉज़ जोड़ना था।
डीजे वैन व्याक

1
क्या ऐसा करने का कोई तरीका है ताकि "कहां" एड हो?
EK_AllDay

11

यदि आप इन-मेमोरी डेटा ("POCO के संग्रह" पढ़ें) के साथ काम कर रहे हैं, तो आप PredicateBuilder का उपयोग करके अपने भावों को एक साथ जोड़ सकते हैं :

// initial "false" condition just to start "OR" clause with
var predicate = PredicateBuilder.False<YourDataClass>();

if (condition1)
{
    predicate = predicate.Or(d => d.SomeStringProperty == "Tom");
}

if (condition2)
{
    predicate = predicate.Or(d => d.SomeStringProperty == "Alex");
}

if (condition3)
{
    predicate = predicate.And(d => d.SomeIntProperty >= 4);
}

return originalCollection.Where<YourDataClass>(predicate.Compile());

उल्लिखित पूर्ण स्रोत PredicateBuilderबलो है (लेकिन आप कुछ और उदाहरणों के साथ मूल पृष्ठ भी देख सकते हैं):

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;

public static class PredicateBuilder
{
  public static Expression<Func<T, bool>> True<T> ()  { return f => true;  }
  public static Expression<Func<T, bool>> False<T> () { return f => false; }

  public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
                                                      Expression<Func<T, bool>> expr2)
  {
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
    return Expression.Lambda<Func<T, bool>>
          (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
  }

  public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
                                                       Expression<Func<T, bool>> expr2)
  {
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
    return Expression.Lambda<Func<T, bool>>
          (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);
  }
}

नोट : मैंने पोर्टेबल क्लास लाइब्रेरी प्रोजेक्ट के साथ इस दृष्टिकोण का परीक्षण किया है और इसका उपयोग करना है.Compile() इसे काम करने के करना है:

कहाँ (विधेय .Compile () );


वहाँ एक कारण है कि यह इकाई फ्रेमवर्क LINQ के साथ काम नहीं करेगा?
Ciantic

मेरे लिए ईएफ कोर के साथ भी ठीक काम करता है। परिणामी Predicate SQL में सही रूप से अनुवादित है।
थॉमस हिल्बर्ट

5

निश्चित रूप से:

if (useAdditionalClauses) 
{ 
  results = 
    results.Where(o => o.OrderStatus == OrderStatus.Open && 
    o.CustomerID == customerID)  
} 

या .Where()इस तरह से एक और कॉल (हालांकि मुझे नहीं पता कि आप क्यों करना चाहते हैं, जब तक कि यह एक और बूलियन कंट्रोल चर द्वारा विभाजित न हो):

if (useAdditionalClauses) 
{ 
  results = results.Where(o => o.OrderStatus == OrderStatus.Open).
    Where(o => o.CustomerID == customerID);
} 

या फिर एक और पुनर्मूल्यांकन results: `परिणाम = परिणाम। कहां ( ब्लाह )।


2

आप && का उपयोग कर सकते हैं और सभी शर्तों को उसी स्थिति में लिख सकते हैं जहां खंड, या आप कर सकते हैं। कहां () कहां (कहां) (कहां ...) और इसी तरह।


1
results = context.Orders.Where(o => o.OrderDate <= today && today <= o.OrderDate)

आप पहले से ही एक आदेश के साथ काम कर रहे हैं के रूप में चयन uneeded है।


0

बस &&ऑपरेटर का उपयोग करें जैसे आप किसी अन्य कथन के साथ करेंगे, जिसे आपको बूलियन लॉजिक करने की आवश्यकता है।

if (useAdditionalClauses)
{
  results = results.Where(
                  o => o.OrderStatus == OrderStatus.Open 
                  && o.CustomerID == customerID)     
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.