2011-07-28 5 views
156

मेरे पास निम्न कोड है। मुझे त्रुटि मिल रही है:मूल्य प्रकार 'Int32' कास्ट विफल हुआ क्योंकि भौतिक मान शून्य है

"The cast to value type 'Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type."

जब क्रेडिट इतिहास तालिका में कोई रिकॉर्ड नहीं है।

var creditsSum = (from u in context.User 
        join ch in context.CreditHistory on u.ID equals ch.UserID           
        where u.ID == userID 
        select ch.Amount).Sum(); 

मैं शून्य मानों को स्वीकार करने के लिए क्वेरी को कैसे संशोधित कर सकता हूं?

उत्तर

272

एक LINQ करने वाली एसक्यूएल क्वेरी कोड के रूप में क्रियान्वित नहीं है, बल्कि एसक्यूएल में अनुवाद करने के लिए nulls कन्वर्ट करने के लिए। कभी-कभी यह एक "लीकी अबास्ट्रक्शन" होता है जो अप्रत्याशित व्यवहार उत्पन्न करता है।

ऐसा एक मामला शून्य हैंडलिंग है, जहां विभिन्न स्थानों पर अप्रत्याशित नल हो सकते हैं। ...DefaultIfEmpty(0).Sum(0) इस (काफी सरल) मामले में, जहां कोई तत्व और एसक्यूएल के SUM रिटर्न null जबकि सी # हो सकता है में मदद कर सकते हैं उम्मीद 0.

एक अधिक सामान्य दृष्टिकोण ?? जो COALESCE लिए अनुवाद किया जाएगा उपयोग करने के लिए जब भी एक खतरा है है int? को

var creditsSum = (from u in context.User 
       join ch in context.CreditHistory on u.ID equals ch.UserID           
       where u.ID == userID 
       select (int?)ch.Amount).Sum() ?? 0; 

यह पहली डाले सी # संकलक कि इस अभिव्यक्ति वास्तव में null लौट सकते हैं, भले ही Sum() रिटर्न एक int बताने के लिए: उत्पन्न एसक्यूएल एक अप्रत्याशित अशक्त रिटर्न कि। फिर हम null मामले को संभालने के लिए सामान्य ?? ऑपरेटर का उपयोग करते हैं।

इस उत्तर के आधार पर, मैंने LINQ से SQL और LINQ से इकाइयों दोनों के विवरण के साथ blog post लिखा था।

+3

धन्यवाद एंडर्स, DefaultIfEmpty (0) के साथ समाधान .um() मेरे लिए ठीक काम करता है। मैंने दूसरे समाधान (int?) के साथ भी कोशिश की है ... ?? 0 ..., लेकिन यह पहले जैसा ही अपवाद फेंकता है .. – zosim

+0

आखिर में इसका परीक्षण करने और इसे समायोजित करने के लिए चारों ओर मिल गया, इसलिए अब दूसरा संस्करण भी काम करता है। –

+0

Sum() और अन्य कुल फ़ंक्शन एक खाली डेटासेट पर लागू होने पर शून्य वापस आ जाएंगे। उनकी परिभाषा के विपरीत, हकीकत में वे अंतर्निहित प्रकार का एक संक्षिप्त संस्करण लौटाते हैं। – Suncat2000

8

एक नल Amount क्षेत्र के लिए अनुमति देने के लिए, बस अशक्त कोलेसिंग ऑपरेटर का उपयोग 0.

var creditsSum = (from u in context.User 
       join ch in context.CreditHistory on u.ID equals ch.UserID           
       where u.ID == userID 
       select ch.Amount ?? 0).Sum(); 
+1

जब मैं अपने टिप का उपयोग करें, संकलक का कहना है: ऑपरेटर '? ? ' प्रकार 'int' और 'int' के संचालन पर लागू नहीं किया जा सकता है। क्या मैं कुछ भूल गया? – zosim

+0

@zosim: यही कारण है कि कलाकार को 'int?' में जोड़ना है। –

+0

मैंने int जोड़ा है, लेकिन एक ही अपवाद। मैं आपके लिए आभारी रहूंगा, जब आपके पास देव env होगा। यह वाक्यविन्यास में क्या गलत है यह जांचने के लिए। – zosim

5

आप aggregate समारोह जो नहीं मिल रहा आइटम कार्रवाई करने के लिए प्रयोग कर रहे हैं, तो आप यह सत्यापित करना होगा LINQ क्वेरी के रूप में नीचे कुछ परिणाम दे रहा है:

var maxOrderLevel =sdv.Any()? sdv.Max(s => s.nOrderLevel):0 
+9

यह एसडीवी दो बार निष्पादित करेगा। IQueryables – Ody

1

मैं इस कोड का इस्तेमाल किया हूँ और यह सही ढंग से प्रतिक्रिया करता है, केवल आउटपुट मान शून्य है।

var packesCount = await botContext.Sales.Where(s => s.CustomerId == cust.CustomerId && s.Validated) 
           .SumAsync(s => (int?)s.PackesCount); 
          if(packesCount != null) 
          { 
           // your code 
          } 
          else 
          { 
           // your code 
          } 
1

मुझे लगता है कि यह प्रश्न पहले से ही उत्तर दिया गया है। लेकिन यदि आप इसे दो बयानों में विभाजित करना चाहते हैं, तो निम्नलिखित पर विचार किया जा सकता है।

var credits = from u in context.User 
       join ch in context.CreditHistory 
        on u.ID equals ch.UserID           
       where u.ID == userID 
       select ch; 

var creditSum= credits.Sum(x => (int?)x.Amount) ?? 0; 
+1

के लिए जो भी आप चाहते हैं वह मेरे लिए काम नहीं करता है ... –

2

जब मैं एक दृश्य से चयन करने के लिए कोशिश कर रहा था यह त्रुटि संदेश था।

समस्या हाल ही में कुछ नई नल पंक्तियां (सब्सक्राइबर आईडी कॉलम में) प्राप्त हुई थी, और इसे ईडीएमएक्स (ईएफ डेटाबेस पहले) में अपडेट नहीं किया गया था।

कॉलम को काम करने के लिए निरर्थक प्रकार होना था।

var dealer = Context.Dealers.Where (x => x.dealerCode == डीलरकोड)।FirstOrDefault();

दृश्य ताज़ा करने से पहले:

public int SubscriberId { get; set; } 

दृश्य ताज़ा करने के बाद:

public Nullable<int> SubscriberId { get; set; } 

हटाया जा रहा है और देखने edmx में जोड़ काम किया।

उम्मीद है कि यह किसी की मदद करेगा।

0

कार्यावधि में इस कोड के साथ इकाई की रूपरेखा 6 में इस त्रुटि मिल गया:

var fileEventsSum = db.ImportInformations.Sum(x => x.FileEvents) 

इस में बदल दिया गया है और फिर इसे काम किया:

var fileEventsSum = db.ImportInformations.Any() ? db.ImportInformations.Sum(x => x.FileEvents) : 0; 
संबंधित मुद्दे