जवाबों:
यदि आप केवल फ़िल्टर करना चाहते हैं यदि कुछ मानदंड पारित किए जाते हैं, तो ऐसा कुछ करें
var logs = from log in context.Logs
select log;
if (filterBySeverity)
logs = logs.Where(p => p.Severity == severity);
if (filterByUser)
logs = logs.Where(p => p.User == user);
इस तरह से करने से आपके एक्सप्रेशन ट्री को वैसा ही होने दिया जाएगा जैसा आप चाहते हैं। इस तरह से बनाई गई एसक्यूएल ठीक वही होगी जो आपको चाहिए और कुछ भी कम नहीं।
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.
यदि आपको सूची / आधार पर आधार को फ़िल्टर करने की आवश्यकता है, तो निम्नलिखित का उपयोग करें:
public List<Data> GetData(List<string> Numbers, List<string> Letters)
{
if (Numbers == null)
Numbers = new List<string>();
if (Letters == null)
Letters = new List<string>();
var q = from d in database.table
where (Numbers.Count == 0 || Numbers.Contains(d.Number))
where (Letters.Count == 0 || Letters.Contains(d.Letter))
select new Data
{
Number = d.Number,
Letter = d.Letter,
};
return q.ToList();
}
मैंने डैरन के समान उत्तर का उपयोग करके समाप्त कर दिया, लेकिन एक IQueryable इंटरफ़ेस के साथ:
IQueryable<Log> matches = m_Locator.Logs;
// Users filter
if (usersFilter)
matches = matches.Where(l => l.UserName == comboBoxUsers.Text);
// Severity filter
if (severityFilter)
matches = matches.Where(l => l.Severity == comboBoxSeverity.Text);
Logs = (from log in matches
orderby log.EventTime descending
select log).ToList();
डेटाबेस मारने से पहले क्वेरी बनाता है। कमांड अंत तक नहीं चलेगी .ToList () अंत में।
जब यह सशर्त लाइनक की बात आती है, तो मैं फिल्टर और पाइप पैटर्न के बहुत शौकीन हूं।
http://blog.wekeroad.com/mvc-storefront/mvcstore-part-3/
मूल रूप से आप प्रत्येक फ़िल्टर केस के लिए एक एक्सटेंशन विधि बनाते हैं जो IQueryable और एक पैरामीटर में होती है।
public static IQueryable<Type> HasID(this IQueryable<Type> query, long? id)
{
return id.HasValue ? query.Where(o => i.ID.Equals(id.Value)) : query;
}
LINQ को धाराप्रवाह अभिव्यक्ति के बीच सशर्त रूप से सक्षम करने की अनुमति देने के लिए मैंने इसे एक एक्सटेंशन विधि के साथ हल किया। यह if
बयानों के साथ अभिव्यक्ति को तोड़ने की आवश्यकता को दूर करता है ।
.If()
विस्तार विधि:
public static IQueryable<TSource> If<TSource>(
this IQueryable<TSource> source,
bool condition,
Func<IQueryable<TSource>, IQueryable<TSource>> branch)
{
return condition ? branch(source) : source;
}
यह आपको ऐसा करने की अनुमति देता है:
return context.Logs
.If(filterBySeverity, q => q.Where(p => p.Severity == severity))
.If(filterByUser, q => q.Where(p => p.User == user))
.ToList();
यहां एक IEnumerable<T>
संस्करण भी है जो अधिकांश अन्य LINQ अभिव्यक्तियों को संभालेगा:
public static IEnumerable<TSource> If<TSource>(
this IEnumerable<TSource> source,
bool condition,
Func<IEnumerable<TSource>, IEnumerable<TSource>> branch)
{
return condition ? branch(source) : source;
}
एक और विकल्प यहाँ पर चर्चा की गई PredicateBuilder की तरह कुछ का उपयोग करना होगा । यह आपको निम्नलिखित की तरह कोड लिखने की अनुमति देता है:
var newKids = Product.ContainsInDescription ("BlackBerry", "iPhone");
var classics = Product.ContainsInDescription ("Nokia", "Ericsson")
.And (Product.IsSelling());
var query = from p in Data.Products.Where (newKids.Or (classics))
select p;
ध्यान दें कि मुझे केवल यह Linq 2 SQL के साथ काम करने के लिए मिला है। EntityFramework एक्सप्रेशन को लागू नहीं करता है। इंवोक, जो इस विधि को काम करने के लिए आवश्यक है। मेरे पास इस मुद्दे के बारे में एक सवाल है ।
यह कर रहा हूं:
bool lastNameSearch = true/false; // depending if they want to search by last name,
इस where
कथन में:
where (lastNameSearch && name.LastNameSearch == "smith")
अर्थ यह है कि जब अंतिम क्वेरी बनाई गई है, अगर lastNameSearch
है false
क्वेरी पूरी तरह से अंतिम नाम खोज के लिए कोई SQL छोड़ देगा।
यह सबसे सुंदर बात नहीं है, लेकिन आप एक लंबोदर अभिव्यक्ति का उपयोग कर सकते हैं और वैकल्पिक रूप से अपनी शर्तों को पारित कर सकते हैं। TSQL में मैं मापदंडों को वैकल्पिक बनाने के लिए बहुत कुछ करता हूं:
कहाँ फ़ील्ड = @ फ़ीडलवर या @ फ़िल्डवर NULL है
आप निम्न लैम्ब्डा के साथ एक ही शैली की नकल कर सकते हैं (प्रमाणीकरण की जाँच का एक उदाहरण):
MyDataContext db = new MyDataContext ();
शून्य RunQuery (स्ट्रिंग param1, स्ट्रिंग param2, int; param3) {
फ़ंक चेकयूज़र = उपयोगकर्ता =>
((param1.Length> 0)? user.Param1 == param1: 1 == 1) &&
((param2.Length> 0)? user.Param2 == param2: 1 == 1) &&
((param3! = null); user.Param3 == param3: 1 == 1);
उपयोगकर्ता फाउंडर = db.Users.SingleOrDefault (चेकयूज़र);
}
मुझे हाल ही में इसी तरह की आवश्यकता थी और अंततः उसने एमएसडीएन में यह पाया। दृश्य स्टूडियो 2008 के लिए CSharp नमूने
डाउनलोड के डायनेमिक® नमूने में शामिल कक्षाएं आपको निम्नलिखित प्रारूप में रनटाइम पर गतिशील प्रश्न बनाने की अनुमति देती हैं:
var query =
db.Customers.
Where("City = @0 and Orders.Count >= @1", "London", 10).
OrderBy("CompanyName").
Select("new(CompanyName as Name, Phone)");
इसका उपयोग करके आप रनटाइम पर एक क्वेरी स्ट्रिंग को गतिशील रूप से बना सकते हैं और इसे कहां () विधि में पास कर सकते हैं:
string dynamicQueryString = "City = \"London\" and Order.Count >= 10";
var q = from c in db.Customers.Where(queryString, null)
orderby c.CompanyName
select c;
बस C # का && ऑपरेटर का उपयोग करें:
var items = dc.Users.Where(l => l.Date == DateTime.Today && l.Severity == "Critical")
संपादित करें: आह, और अधिक ध्यान से पढ़ने की जरूरत है। आप जानना चाहते थे कि सशर्त रूप से अतिरिक्त क्लॉस कैसे जोड़े जाएँ। उस मामले में, मुझे कोई पता नहीं है। :) मैं जो कर सकता हूं वह सिर्फ कई प्रश्नों को तैयार करना है, और सही एक को निष्पादित करना है, जो मुझे ज़रूरत है उसके आधार पर।
आप एक बाहरी विधि का उपयोग कर सकते हैं:
var results =
from rec in GetSomeRecs()
where ConditionalCheck(rec)
select rec;
...
bool ConditionalCheck( typeofRec input ) {
...
}
यह काम करेगा, लेकिन अभिव्यक्ति के पेड़ में नहीं तोड़ा जा सकता है, जिसका अर्थ है कि लाइनक टू SQL हर रिकॉर्ड के खिलाफ चेक कोड चलाएगा।
वैकल्पिक रूप से:
var results =
from rec in GetSomeRecs()
where
(!filterBySeverity || rec.Severity == severity) &&
(!filterByUser|| rec.User == user)
select rec;
यह अभिव्यक्ति के पेड़ों में काम कर सकता है, जिसका अर्थ है कि लिनक्यू टू एसक्यूएल को अनुकूलित किया जाएगा।
खैर, जो मैंने सोचा था कि आप फ़िल्टर शर्तों को Predicates की एक सामान्य सूची में डाल सकते हैं:
var list = new List<string> { "me", "you", "meyou", "mow" };
var predicates = new List<Predicate<string>>();
predicates.Add(i => i.Contains("me"));
predicates.Add(i => i.EndsWith("w"));
var results = new List<string>();
foreach (var p in predicates)
results.AddRange(from i in list where p.Invoke(i) select i);
इस सूची में "me", "meyou", और "mow" शामिल हैं।
आप यह भविष्यवाणी कर सकते हैं कि एक पूरी तरह से अलग कार्य में भविष्यवाणी के साथ फोरकास्ट करने से ओआरएस सभी भविष्यवाणी करता है।