2010-07-18 10 views
38

पर MAX पर कॉल करने वाले इकाई फ्रेमवर्क एक IQueryable पर मैक्स() को कॉल करते समय और शून्य रिकॉर्ड हैं, मुझे निम्न अपवाद मिलता है।रिकॉर्ड्स

मूल्य प्रकार 'Int32' में कास्ट विफल हुआ क्योंकि भौतिक मूल्य शून्य है। या तो परिणाम प्रकार का सामान्य पैरामीटर या क्वेरी को एक शून्य प्रकार का उपयोग करना चाहिए।

var version = ctx.Entries 
    .Where(e => e.Competition.CompetitionId == storeCompetition.CompetitionId) 
    .Max(e => e.Version); 

अब मैं समझता हूँ कि ऐसा क्यों होता मेरे सवाल का कैसे करता है, तो तालिका खाली कर सकते हैं यह करने के लिए सबसे अच्छा तरीका है। नीचे दिया गया कोड काम करता है और इस समस्या को हल करता है, लेकिन इसकी बहुत बदसूरत कोई MaxOrDefault() अवधारणा नहीं है?

int? version = ctx.Entries 
    .Where(e => e.Competition.CompetitionId == storeCompetition.CompetitionId) 
    .Select(e => (int?)e.Version) 
    .Max(); 
+0

एफई का कौन सा संस्करण का उपयोग कर रहे हैं परिणाम प्रकार सेट मतलब यह इस्तेमाल कर सकते हैं ? – jrista

+0

माइक्रोसॉफ्ट एडीओ.NET इकाई फ्रेमवर्क फ़ीचर सामुदायिक प्रौद्योगिकी पूर्वावलोकन 4 – bleevo

उत्तर

68

हाँ, टी की Nullable पर कास्ट संस्थाओं प्रश्नों का LINQ में समस्या से निपटने के सिफारिश तरीका है। एक MaxOrDefault() विधि जिसमें सही हस्ताक्षर है, एक दिलचस्प विचार की तरह लगता है, लेकिन आपको इस समस्या को प्रस्तुत करने वाली प्रत्येक विधि के लिए एक अतिरिक्त संस्करण की आवश्यकता होगी, जो बहुत अच्छी तरह से स्केल नहीं करेगा।

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

यहां एक समाधान है जो आपके पास जो कुछ है उससे थोड़ा सरल दिखता है उपरोक्त:

var version = ctx.Entries 
    .Where(e => e.Competition.CompetitionId == storeCompetition.CompetitionId) 
    .Max(e =>(int?)e.Version); 

उम्मीद है कि इससे मदद मिलती है।

+0

हे डिवेगा, मेरा जवाब देखें क्या आप इस दृष्टिकोण के साथ कोई समस्या देखते हैं? – bleevo

+0

bleevo, मुझे डर है जब तक कि आप IQueryable और अभिव्यक्ति > तर्क लेने के लिए अपनी विधि बदल नहीं लेते हैं, तो विधि निश्चित रूप से LINQ से ऑब्जेक्ट्स के साथ क्लाइंट-साइड मूल्यांकन पर स्विच करेगी। व्यक्तिगत रूप से, मुझे लगता है कि सिर्फ टी कास्टिंग? सरल है – divega

+0

एसओ, डिएगो में आपका स्वागत है! यहां आपको देखकर अच्छा लगा! –

2

मैं किसी उत्तर के लिए नहीं ले सकता :) मैंने नीचे परीक्षण किया है और यह काम करता है, मैंने अभी तक जेनरेट की गई एसक्यूएल की जांच की है, इसलिए सावधान रहें, मैं इसे और अधिक परीक्षण करने के बाद इसे अपडेट कर दूंगा।

var test = ctx.Entries 
    .Where(e => e.Competition.CompetitionId == storeCompetition.CompetitionId) 
    .MaxOrDefault(x => x.Version); 

public static TResult? MaxOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) 
    where TResult : struct 
{ 
    return source 
     .Select(selector) 
     .Cast<TResult?>() 
     .Max(); 
} 
+1

यह एक एल 2 ई क्वेरी नहीं है। यह एल 2 ओ है। यह ठीक है, लेकिन यह नहीं है कि आपने क्या पूछा। :) –

+0

हां, फिर ड्राइंग बोर्ड पर आपका सही वापस! – bleevo

13

अपने अधिकतम के लिए डिफ़ॉल्ट बनाने के लिए इसे आज़माएं।

int version = ctx.Entries 
    .Where(e => e.Competition.CompetitionId == storeCompetition.CompetitionId) 
    .Max(e =>(int?)e.Version) ?? 0; 
+4

स्वीकृत उत्तर एक निरर्थक int देता है। आपका उत्तर एक गैर-निरर्थक int वापस करने का एक संक्षिप्त तरीका है, जो मेरे लिए अधिक उपयोगी था। – kevinpo

0

इस प्रयास करें:

IEnumerable<AlertsResultset> alerts = null; 

    alerts = (from POA in SDSEntities.Context.SDS_PRODUCT_ORDER_ALERT 
       join A in SDSEntities.Context.SDS_ALERT on POA.ALERT_ID equals A.ALERT_ID 
       orderby POA.DATE_ADDED descending 
       select new AlertsResultset 
       { 
        ID = POA.PRODUCT_ORDER_ALERT_ID == null ? 0:POA.PRODUCT_ORDER_ALERT_ID , 
        ITEM_ID = POA.ORDER_ID.HasValue ? POA.ORDER_ID.Value : POA.PRODUCT_ID.Value, 
        Date = POA.DATE_ADDED.Value, 
        orderType = SDSEntities.Context.SDS_ORDER.Where(o => o.ORDER_ID == POA.ORDER_ID.Value).FirstOrDefault().ORDER_TYPE, 
        TransactionNumber = POA.PRODUCT_ID.HasValue ? (SDSEntities.Context.SDS_PRODUCT.Where(p => p.PRODUCT_ID == POA.PRODUCT_ID.Value).FirstOrDefault().TRANSACTION_NUMBER) : (SDSEntities.Context.SDS_ORDER.Where(o => o.ORDER_ID == POA.ORDER_ID.Value).FirstOrDefault().TRANSACTION_NUMBER), 
        Publisher = POA.PRODUCT_ID.HasValue ? 
        (
        SDSEntities.Context.SDS_PRODUCT.Where(p => p.PRODUCT_ID == POA.PRODUCT_ID.Value).FirstOrDefault().PRODUCT_TYPE_NUMBER == "ISSUE" ? (from prod in SDSEntities.Context.SDS_PRODUCT 
                                         join ji in SDSEntities.Context.SDS_JOURNAL_ISSUE on prod.PRODUCT_ID equals ji.PRODUCT_ID 
                                         join j in SDSEntities.Context.SDS_JOURNAL on ji.JOURNAL_ID equals j.JOURNAL_ID 
                                         where prod.PRODUCT_ID == POA.PRODUCT_ID 
                                         select new { j.PUBLISHER_NAME }).FirstOrDefault().PUBLISHER_NAME : (from prod in SDSEntities.Context.SDS_PRODUCT 
                                                          join bi in SDSEntities.Context.SDS_BOOK_INSTANCE on prod.PRODUCT_ID equals bi.PRODUCT_ID 
                                                          join b in SDSEntities.Context.SDS_BOOK on bi.BOOK_ID equals b.BOOK_ID 
                                                          where prod.PRODUCT_ID == POA.PRODUCT_ID 
                                                          select new { b.PUBLISHER_NAME }).FirstOrDefault().PUBLISHER_NAME 
       ) 
        : (SDSEntities.Context.SDS_ORDER.Where(o => o.ORDER_ID == POA.ORDER_ID.Value).FirstOrDefault().PUBLISHER_NAME), 
        Alert = A.ALERT_NAME, 
        AlertType = A.ALERT_TYPE, 
        IsFlagged = POA.IS_FLAGGED.Value, 
        Status = POA.ALERT_STATUS 
       }); 
4

आप इस तरह एक सरल विस्तार विधि लिख सकता है, यह प्रकार टी का डिफ़ॉल्ट मान लौटाता है यदि कोई रिकॉर्ड मौजूद हैं और फिर उस के लिए अधिकतम लागू या क्वेरी यदि है रिकॉर्ड मौजूद हैं।

public static T MaxOrEmpty<T>(this IQueryable<T> query) 
{ 
    return query.DefaultIfEmpty().Max(); 
} 

और आप जैसे

maxId = context.Competition.Select(x=>x.CompetitionId).MaxOrEmpty(); 
+0

इस समाधान के बारे में अच्छी बात यह है कि आप एक डिफ़ॉल्ट मान निर्दिष्ट कर सकते हैं (DefaultIfEmpty (मान))। तो आपको एक शून्य प्रकार वापस करने की ज़रूरत नहीं है। – robert

0

के बारे में क्या इस
query.Max<TSource,TResult?>(selector) 

मैं स्पष्ट रूप से व्यर्थ होने के लिए

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