2010-06-01 9 views
54

में बाध्य नहीं था मुझे एक गतिशील फ़िल्टर बनाने की आवश्यकता थी और मैं इकाइयों का उपयोग करना चाहता था। इस कारण से मैं अल्फाहारी से प्रिडिकेटबिल्डर का उपयोग करना चाहता था।सी # भविष्यवाणी बिल्डर इकाइयां: पैरामीटर 'एफ' निर्दिष्ट LINQ से इकाई क्वेरी अभिव्यक्ति

मैं निम्नलिखित कोड बनाया:

var invoerDatums = PredicateBuilder.True<OnderzoeksVragen>(); 
var inner = PredicateBuilder.False<OnderzoeksVragen>(); 

foreach (var filter in set.RapportInvoerFilter.ToList()) 
{ 
    if(filter.IsDate) 
    { 
     var date = DateTime.Parse(filter.Waarde); 
     invoerDatums = invoerDatums.Or(o => o.Van >= date && o.Tot <= date); 
    } 
    else 
    { 
     string temp = filter.Waarde; 
     inner = inner.Or(o => o.OnderzoekType == temp); 
    } 
} 

invoerDatums = invoerDatums.And(inner); 
var onderzoeksVragen = entities.OnderzoeksVragen 
           .AsExpandable() 
           .Where(invoerDatums) 
           .ToList(); 

जब मैं कोड भाग गया केवल 1 फिल्टर जो एक तारीख फिल्टर नहीं था नहीं था। तो केवल आंतरिक भविष्यवाणी भर गई थी। जब पूर्वानुमान निष्पादित किया गया था तो मुझे निम्न त्रुटि मिली।

पैरामीटर 'एफ' संस्थाओं को निर्दिष्ट LINQ में बाध्य नहीं था अभिव्यक्ति क्वेरी।

उत्तर के लिए खोज करते समय मुझे निम्नलिखित page मिला। लेकिन यह पहले से ही LINQKit में लागू किया गया है।

क्या किसी और ने इस त्रुटि का अनुभव किया है और इसे हल करने का तरीका पता है?

उत्तर

121

मैं एक ही त्रुटि भर में भाग गया, इस मुद्दे को जब मुझे लगता है कि अन्य PredicateBuilder

साथ

बनाया विधेय से बना बारी में थे PredicateBuilder के साथ बनाया विधेय था लग रहा था जैसे कि (ए या बी) और (एक्स या वाई) जहां एक निर्माता ए या बी बनाता है, एक एक्स या वाई बनाता है और एक तिहाई और उन्हें एक साथ बनाता है।

भविष्यवाणी के केवल एक स्तर के साथ AsExpandable ठीक काम किया, जब एक से अधिक स्तर पेश किए गए तो मुझे एक ही त्रुटि मिली।

मुझे कोई मदद नहीं मिली लेकिन कुछ परीक्षण और त्रुटि के माध्यम से मैं काम करने में सक्षम था। हर बार जब मैंने भविष्यवाणी की तो मैंने विस्तार विस्तार विधि के साथ इसका पालन किया। ConstructOptionNotMatchPredicate एक अभिव्यक्ति देता है

public static IQueryable<Submission> AddOptionFilter(
    this IQueryable<Submission> query, 
    IEnumerable<IGrouping<int, int>> options) 
{ 
    var predicate = options.Aggregate(
     PredicateBuilder.False<Submission>(), 
     (accumulator, optionIds) => accumulator.Or(ConstructOptionMatchPredicate(optionIds).Expand())); 
     query = query.Where(predicate.Expand());    
    return query; 
} 

क्वेरी एक IQueryable जो पहले से ही किया गया है AsExpandable कहा जाता है,:

यहाँ कोड का एक सा, सादगी के लिए कटौती है।

एक बार जब हम त्रुटि को पार कर गए तो हम निश्चित रूप से इकाई फ्रेमवर्क के खिलाफ रनटाइम पर जटिल फ़िल्टर बनाने में सक्षम थे।

संपादित करें:

के बाद से लोगों को अभी भी पर टिप्पणी कर रहे हैं और इस मतदान मुझे लगता है यह अभी भी उपयोगी है तो मैं एक और ठीक साझा कर रहा हूँ। मूल रूप से मैंने इस Universal Predicate Builder के पक्ष में लिंककिट और इसके अनुमानित निर्माता का उपयोग करना बंद कर दिया है, जिसमें एक ही एपीआई है लेकिन कॉल का विस्तार करने की आवश्यकता नहीं है, अच्छी तरह जांच करने योग्य है।

+0

मुझे अपने मूल IQueryable ऑब्जेक्ट से AsExpandable() को कॉल को भी हटाना पड़ा। –

+2

अच्छा जवाब, लेकिन भ्रामक। ब्लडबाज़ का जवाब सरल और अधिक सही उत्तर है – Mick

44

मैं यह त्रुटि आई और Mant101 के विवरण मुझे जवाब मिल गया है, लेकिन आप एक सरल उदाहरण है कि समस्या का कारण बनता है की तलाश में हो सकता है:

// This predicate is the 1st predicate builder 
var predicate = PredicateBuilder.True<Widget>(); 

// and I am adding more predicates to it (all no problem here) 
predicate = predicate.And(c => c.ColumnA == 1); 
predicate = predicate.And(c => c.ColumnB > 32); 
predicate = predicate.And(c => c.ColumnC == 73); 

// Now I want to add another "AND" predicate which actually comprises 
// of a whole list of sub-"OR" predicates 
if(keywords.Length > 0) 
{ 
    // NOTICE: Here I am starting off a brand new 2nd predicate builder.... 
    // (I'm not "AND"ing it to the existing one (yet)) 
    var subpredicate = PredicateBuilder.False<Widget>(); 

    foreach(string s in keywords) 
    { 
     string t = s; // s is part of enumerable so need to make a copy of it 
     subpredicate = subpredicate.Or(c => c.Name.Contains(t)); 
    } 

    // This is the "gotcha" bit... ANDing the independent 
    // sub-predicate to the 1st one.... 

    // If done like this, you will FAIL! 
// predicate = predicate.And(subpredicate); // FAIL at runtime! 

    // To correct it, you must do this... 
    predicate = predicate.And(subpredicate.Expand()); // OK at runtime! 
} 

आशा इस मदद करता है! :-)

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