2012-02-14 15 views
5

मैं इस समस्या पर कुछ समय के लिए अपने सिर पर टक्कर लगी हूं। कुछ समान मामले हैं, लेकिन मेरे मामले पर समाधान लागू नहीं थे।गतिशील LINQ (इकाइयों के लिए) जहां शून्य दिनांक दिनांक कॉलम

मेरे पास एक तरीका है जो स्ट्रिंग प्रारूप में फ़िल्टर क्वेरी देता है। विधि विभिन्न डेटा प्रकार के लिए तर्क है, सही मान, स्तंभ नाम आदि

string filterQuery = GetFilterQuery(params); 
rows = rows.Where(filterQuery); 

मेरे समस्या यह है कि मैं डेटाबेस में Nullable DateTime है और मैं कोड पक्ष में String प्रतिनिधित्व है निर्धारित करता है।

निम्नलिखित मैं कोशिश की है प्रश्नों (String प्रतिनिधित्व गलत वर्तमान में हो सकता है):

"BirthDate.ToString() = \"16.2.2012 22:00:00\"" 

परिणाम: '? दिनांक समय' तरीके प्रकार पर

"BirthDate.Value.ToString() = \"16.2.2012 22:00:00\"" 

परिणाम सुलभ नहीं हैं: संस्थाओं को LINQ विधि 'System.String ToString()' विधि को नहीं पहचानता है, और इस विधि एक दुकान अभिव्यक्ति में अनुवाद नहीं किया जा सकता है।

"BirthDate == null ? 1=1 : (DateTime)BirthDate.ToString() = \"16.2.2012 22:00:00\"" 

परिणाम: '।' या '(' उम्मीद

कैसे एक वर्ग फ़िल्टर समस्या को हल करने?

अद्यतन (अधिक स्रोत कोड क्वेरी पीढ़ी)

var filterQueries = query.GridFilteringOptions.filters 
    // remove filters that doesn't have all the required information 
    .Where(o => o.name != string.Empty && o.value != string.Empty && !string.IsNullOrEmpty(o.type)) 
    // remove filters that are filtering other tables than current 
    .Where(o => o.table == tableName) 
    .Select(filter => filter.ResolveQuery()).ToList(); 

if (filterQuery.Any()) 
{ 
    var filterQuery = string.Join(" And ", filterQueries); 
    rows = rows.Where(filterQuery); 
} 

और यहाँ के बारे में जोड़ा जाता है और तरीके हैं कोई भी विचार

इस संदर्भ से संबंधित

public string ResolveQuery() 
{ 
    if (type == "Int64") 
    { 
     return ResolveInteger(); 
    } 
    else if(type == "String") 
    { 
     return ResolveString(); 
    } 
    else if(type == "DateTime") 
    { 
     return ResolveDateTime(); 
    } 
    else 
    { 
     return string.Empty; 
    } 
} 

private string ResolveDateTime() 
{ 
    DateTime result = new DateTime(); 
    if (DateTime.TryParse(this.value, out result)) 
    { 
     return string.Format("{0}.ToString() = \"{1}\"", this.name, result.ToUniversalTime()); 
    } 
    return string.Empty; 
} 

private string ResolveString() 
{ 
    switch (@operator) 
    { 
     default: 
      return string.Format(@"{0}.StartsWith(""{1}"")", this.name, this.value); 
    }    
} 

private string ResolveInteger() 
{ 
    string tmp = this.name; 
    switch (@operator) 
    { 
     case -1: 
      return string.Empty; 
     case 0: 
      tmp += "<"; 
      break; 
     case 1: 
      tmp += "="; 
      break; 
     case 2: 
      tmp += ">"; 
      break; 
     default: 
      return string.Empty; 
    } 
    tmp += value; 
    return tmp; 
} 

उत्तर

2

LINQ से इकाइयों कोपहचान नहीं हैविधि। परिणामस्वरूप स्ट्रिंग को अपनी क्वेरी में डालने से पहले आपको इसका मूल्यांकन करना होगा।

अपने प्रश्न में उदाहरण बनाने के लिए आप इस तरह इसे संभाल सकता है: क्योंकि LINQ एफई के लिए त्रिगुट ऑपरेटर को नहीं पहचानता है

// "BirthDate.ToString() = \"16.2.2012 22:00:00\"" 
string birthdate = BirthDate.ToString(); 
string query = String.Format("{0} = \"16.2.2012 22:00:00\"", birthdate); 

// "BirthDate.Value.ToString() = \"16.2.2012 22:00:00\"" 
string birthdate = BirthDate.Value.ToString(); 
string query = String.Format("{0} = \"16.2.2012 22:00:00\"", birthdate); 

"BirthDate == null ? 1=1 : (DateTime)BirthDate.ToString() = \"16.2.2012 22:00:00\"" शायद काम नहीं करता है (? :)

संपादित करें: मैं आपकी टिप्पणी से समझता हूं कि BirthDate आपकी तालिका में एक कॉलम है, एक चर नहीं।इस मामले में आप, सभी प्रविष्टियों प्राप्त कर सकते हैं उन्हें एक सूची में बदलने और उसके बाद इस तरह वस्तुओं के लिए फिल्टर LINQ का उपयोग कर लागू (यद्यपि आप उसके अनुसार अपनी filterQuery को संशोधित करने के लिए होता है):

string filterQuery = GetFilterQuery(params); 
var filteredRows = rows.ToList().Where(filterQuery); 

untested है: यह हो सकता है अपने डेटाबेस के CONVERT समारोह का उपयोग संभव हो:

string query = "CONVERT(varchar(20), BirthDate) = \"16.2.2012 22:00:00\""; 
+0

जन्मदिन। टोस्टिंग() - इस संदर्भ में जन्मदिन क्या है? मेरे मामले में सिर्फ एक कॉलम नाम है, इसलिए यह कोड संदर्भ में मौजूद नहीं है। – Tx3

+0

मैं देखता हूं। मेरे अद्यतन उत्तर पर एक नज़र डालें। –

+0

धन्यवाद, मैं अवांछित दृष्टिकोण भी कोशिश करूंगा – Tx3

0

मेरे समस्या यह है कि मैं डेटाबेस में Nullable दिनांक समय है और मैं कोड पक्ष में स्ट्रिंग प्रतिनिधित्व है।

क्यों?

कोड पक्ष बदलें, स्ट्रिंग प्रतिनिधित्व को पार्स करें और इसे LINQ क्वेरी में उचित ऑब्जेक्ट दें।

"BirthDate.ToString() = \" 2012/02/16 22: 00: "

खराब 00 \" - आप स्ट्रिंग manipulatzion करने के लिए है, तो AWLWAYS InvariantCulture का उपयोग करें। यह कोड नाजुक है और किसी अन्य देश में टूट जाएगा।

+0

दिनांक स्ट्रिंग प्रारूप इस प्रश्न में प्रासंगिक नहीं है। हां, यह उदाहरण कोड में ठीक तरह से स्वरूपित नहीं है। इसे यूटीसी पूर्णांक में बदला जा सकता है। जो मैं पूरा करने की कोशिश करता हूं वह यह है कि मेरे पास एक विधि होगी जो स्ट्रिंग प्रारूप में वैध "खोज मानदंड" लौटाती है, ताकि इसे सभी प्रकार के दिनांक प्रकारों के लिए आसानी से उपयोग किया जा सके। यदि आवश्यक हो तो मैं निरर्थक डेटटाइम पर अपवाद कर सकता हूं, लेकिन मैं इसके बजाय इसे टालना चाहूंगा। – Tx3

+0

आप निश्चित रूप से InvariantCulture के बारे में सही हैं और कोड वर्तमान में नाजुक हैं। – Tx3

+0

नहीं किया जा सकता है। एसक्यूएल पर दिनांक के समय में "बीच" को छोड़कर खोज करने का कोई प्रभावी तरीका नहीं है, और LINQ क्या कर सकता है यहां सीमित है। आपका सामान्य दृष्टिकोण बेहतर LINQ pricicularities को ध्यान में रखता है। – TomTom

0

मैं वर्तमान में इसे एक कोशिश/पकड़ ब्लॉक के साथ हल करता हूं। यही कारण है कि कुछ भूमि के ऊपर और कुरूपता कि मैं नहीं बल्कि के लिए एक वैकल्पिक मिलेगा कहते हैं, लेकिन यह बहुत मजबूत काम करता है:

try 
{ 
    // for strings and other non-nullables 
    records = records.Where(rule.field + ".ToString().Contains(@0)", rule.data); 
} 
catch (System.Linq.Dynamic.ParseException) 
{ 
    // null types 
    records = records.Where(rule.field + ".Value.ToString().Contains(@0)", rule.data); 
} 

नोट: इनपुट चर (rule.field और rule.data) से उन क्षेत्रों को स्वीकार करना खतरनाक है, और आप खोल सकते हैं एक (मुश्किल) अंधेरे एसक्यूएल इंजेक्शन तक। पहले मान (rule.field) को रोकने के लिए मूल्यों की श्वेतसूची के खिलाफ जांच की जा सकती है।

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