2009-09-17 14 views
11

मैं एक सादे पुराने CLR वस्तु जो अनिवार्य रूप से दो इकाई की रूपरेखा वस्तुओं के लिए एक आवरण है के लिए LINQ में टाइप वस्तुओं शुरु कर रहा है, मैं यह कर रहा हूँ तो मैं MVC ढांचे में एक जोरदार टाइप किया दृश्य को यह आवरण वस्तु पारित कर सकते हैं ।दृढ़ता से संस्थाओं

public IEnumerable<FooWrapper> ListFoosWithBars(int userID) 
{ 
    IEnumerable<Bar> tempBar = ListBarsByUserID(userID); 
    IEnumerable<FooWrapper> results = (from f in _entities.FooSet 
             join b in tempBar on f.ID equals b.foos.ID 
             select new FooWrapper(f, b)); 
    return results; 
} 

यह संस्थाओं क्योंकि जाहिर LINQ काम नहीं करता है parametrized का समर्थन नहीं करता:

public class FooWrapper 
{ 
    public FooWrapper(Foo f, Bar b) 
    { 
     this.FooObject = f; 
     this.BarObject = b; 
    } 

    public Foo FooObject { get; private set; } 
    public Bar BarObject { get; private set; } 
} 

क्या मैं अब तक मेरी ListFoosWithBars समारोह के लिए है इस प्रकार है: मेरे foo आवरण वर्ग बहुत सरल है प्रारंभिकरण, एक अपवाद फेंक दिया गया है जो कहता है: "LINQ से इकाइयों में केवल पैरामीटर रहित कन्स्ट्रक्टर और प्रारंभकर्ता समर्थित हैं।" मैं सोच रहा था कि क्या यही परिणाम प्राप्त करने का दूसरा तरीका है?

उत्तर

20

आप अपने FooWrapper करने के लिए एक parameterless निर्माता जोड़ते हैं और फिर बजाय वस्तु आरंभीकरण उपयोग करते हैं, तो जैसे:

public IEnumerable<FooWrapper> ListFoosWithBars(int userID) 
{ 
    IEnumerable<Bar> tempBar = ListBarsByUserID(userID); 

    IEnumerable<FooWrapper> results = (
     from f in _entities.FooSet 
     join b in tempBar on f.ID equals b.foos.ID 
     select new FooWrapper() 
     { 
      FooObject = f, 
      BarObject = b 
     }); 

    return results; 
} 
+3

वही बात टाइप की गई थी, तो आप जीत गए। – AdamSane

+0

बिल्कुल सही, धन्यवाद! प्रारंभकर्ता में टाइप नाम के बाद छोड़ने के लिए –

3

एक अलग आरंभीकरण का प्रयास करें:

public class FooWrapper 
{ 
    public FooWrapper() { } 

    public Foo FooObject { get; set; } 
    public Bar BarObject { get; set; } 
} 


public IEnumerable<FooWrapper> ListFoosWithBars(int userID) 
{ 
    IEnumerable<Bar> tempBar = ListBarsByUserID(userID); 

    IEnumerable<FooWrapper> results = (
     from f in _entities.FooSet 
     join b in tempBar on f.ID equals b.foos.ID 
     select new FooWrapper 
     { 
      FooObject = f, 
      BarObject = b 
     }); 

    return results; 
} 
+1

+1। :) –

12

ठीक है, लेकिन क्या आप FooObject चाहते हैं और BarObject पढ़ने के लिए? यह मेरे लिए थोड़ा सा पीछे लगता है कि वे वस्तु पर एक निर्माता का उपयोग करने की क्षमता को अस्वीकार करते हैं।

मैं आदेश इस परिदृश्य में वस्तु प्रारंभ का उपयोग करने में अच्छा कैप्सूलीकरण प्रथाओं को तोड़ने के बहुत से लोगों को देख सकते हैं।

6

तुम क्यों .AsEnumerable() का उपयोग नहीं कर रहे हैं? इस तरह, आपको एक पैरामीटर रहित कन्स्ट्रक्टर बनाने की आवश्यकता नहीं होगी और यही वह है जो आप चाहते हैं।

आपका कोड लगभग अच्छा था। इसे इस पर बदलें:

public IEnumerable<FooWrapper> ListFoosWithBars(int userID) 
{ 
    IEnumerable<Bar> tempBar = ListBarsByUserID(userID); 
    IEnumerable<FooWrapper> results = (from f in _entities.FooSet.AsEnumerable() 
             join b in tempBar on f.ID equals b.foos.ID 
             select new FooWrapper(f, b)); 
    return results; 
} 

मुझे आज भी यही समस्या थी। मेरे पास एक पैरामीटर कन्स्ट्रक्टर वाला वर्ग था। इस कन्स्ट्रक्टर ने एक निजी रीडोनली फ़ील्ड भर दिया जो एक संपत्ति द्वारा केवल एक सेट के साथ प्राप्त नहीं किया गया था।

+0

यह इस मुद्दे के लिए अब तक का सबसे अच्छा समाधान है! –

+8

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

+0

@ सैंटो सहमत, इस दृष्टिकोण से मेरी मशीन को 16 टेबलों पर LINQ कथन के साथ रोक दिया जाता है, परिणाम देने के लिए लगभग पांच मिनट लगते हैं। एक तुलनात्मक एसक्यूएल कथन के साथ यह लगभग तात्कालिक था। – wonea

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