2010-12-18 13 views
31

मैं एक एएसपीनेट एमवीसी अनुप्रयोग पर काम कर रहा हूं और मेरे नियंत्रकों के लिए कन्स्ट्रक्टर का उपयोग करने के बारे में मेरा कोई प्रश्न है।एएसपीनेट एमवीसी नियंत्रक - कन्स्ट्रक्टर उपयोग

मैं अपने सभी डेटा लेनदेन के लिए संस्थाओं के लिए इकाई फ्रेमवर्क और linq का उपयोग कर रहा हूं। मुझे अपने सभी नियंत्रक कार्यों के लिए अपने एंटिटी मॉडल तक पहुंचने की ज़रूरत है। जब मैंने पहली बार ऐप लिखना शुरू किया, तो मैं प्रत्येक एक्शन विधि की शुरुआत में एक इकाई ऑब्जेक्ट बना रहा था, जो भी काम करने की आवश्यकता थी और फिर मेरा परिणाम लौटा रहा था।

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

मैं अभी भी खुद से पूछताछ कर रहा हूं कि किस तरह से सही है। मैं सोच रहा हूँ ए) कौन सी विधि सबसे उपयुक्त है? बी) कन्स्ट्रक्टर विधि में, ये वस्तुएं कब तक रहती हैं? सी) क्या कन्स्ट्रक्टर विधि के साथ प्रदर्शन/अखंडता मुद्दे हैं?

आप

+0

क्या आपको केवल एक नियंत्रक के लिए इस ऑब्जेक्ट की आवश्यकता है? –

+0

हो सकता है कि आपको निजी स्थिर उदाहरण के साथ सिंगलटन पटर का उपयोग करना चाहिए और आलसी लोडिंग उदाहरण के लिए संपत्ति प्राप्त करें। –

उत्तर

26

आप सही सवाल पूछ रहे हैं धन्यवाद।

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

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

सी। तत्काल लागत शायद न्यूनतम है। डेटाबेस लेनदेन लागत वह जगह है जहां आप शायद अपना ध्यान केंद्रित करना चाहते हैं। 'कार्य की इकाई' नामक एक अवधारणा है जिसे आप देखना चाहते हैं। अनिवार्य रूप से, एक डेटाबेस केवल एक सेव/अपडेट ऑपरेशन से बड़े लेनदेन को संभाल सकता है। लेनदेन के आकार में वृद्धि से बेहतर डीबी प्रदर्शन हो सकता है।

आशा है कि आप शुरू कर लेंगे।

बॉब

+1

निर्भरता इंजेक्शन के लिए निजता का प्रयास करें! – Omkar

+1

"सुनिश्चित करें कि आप अपने कनेक्शन को बंद कर दें (निपटान पर भरोसा करने के बजाय)" - मैं दृढ़ता से असहमत हूं। IDISposable नियंत्रकों को एक नियंत्रक द्वारा निपटाया जाता है, जीसी द्वारा नहीं, और उनका निपटान निर्धारिती है। विवरण के लिए [यह प्रश्न] देखें (http://stackoverflow.com/questions/1380019/asp-mvc-when-is-icontroller- disispose-called)। – Alex

28

आरक्रैवेन्स में कुछ उत्कृष्ट अंतर्दृष्टि हैं। मैं यह दिखाना चाहता हूं कि आप उनके सुझावों को कैसे कार्यान्वित कर सकते हैं।

यह डेटा का उपयोग वर्ग के लिए एक इंटरफेस को परिभाषित करने को लागू करने के द्वारा शुरू करने के लिए अच्छा होगा:

public interface IPostRepository 
{ 
    IEnumerable<Post> GetMostRecentPosts(int blogId); 
} 

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

public class PostRepository : IPostRepository 
{ 
    public IEnumerable<Post> GetMostRecentPosts(int blogId) 
    { 
     // A using statement makes sure the context is disposed quickly. 
     using(var context = new BlogContext()) 
     { 
      return context.Posts 
       .Where(p => p.UserId == userId) 
       .OrderByDescending(p => p.TimeStamp) 
       .Take(10) 
       // ToList ensures the values are in memory before disposing the context 
       .ToList(); 
     } 
    } 
} 

अब आप अपने नियंत्रक एक निर्माता तर्क के रूप में इन खजाने में से एक को स्वीकार कर सकते हैं: तो आपको लगता है कि निर्दिष्ट कर सकते हैं,

public class BlogController : Controller 
{ 
    private IPostRepository _postRepository; 
    public BlogController(IPostRepository postRepository) 
    { 
     _postRepository = postRepository; 
    } 

    public ActionResult Index(int blogId) 
    { 
     var posts = _postRepository.GetMostRecentPosts(blogId); 
     var model = new PostsModel { Posts = posts }; 
     if(!posts.Any()) {model.Message = "This blog doesn't have any posts yet";} 
     return View("Posts", model); 
    } 

} 

MVC आप डिफ़ॉल्ट के एवज में अपने स्वयं के नियंत्रक फैक्टरी का उपयोग करने की अनुमति देता है अपने आईओसी निनजेक्ट की तरह ढांचा तय करता है कि नियंत्रक कैसे बनाए जाते हैं। आप यह जानने के लिए अपना इंजेक्शन ढांचा सेट अप कर सकते हैं कि जब आप किसी IPostRepository के लिए पूछते हैं तो उसे PostRepository ऑब्जेक्ट बनाना चाहिए।

इस दृष्टिकोण का एक बड़ा लाभ यह है कि यह आपके नियंत्रक इकाई-परीक्षण योग्य बनाता है। उदाहरण के लिए, आप सुनिश्चित करें कि आपके मॉडल जब कोई पोस्ट कर रहे हैं एक संदेश हो जाता है बनाना चाहते हैं, तो आप Moq की तरह एक मजाक रूपरेखा एक परिदृश्य स्थापित करने के लिए उपयोग कर सकते हैं, जहां अपने भंडार रिटर्न कोई पोस्ट:

var repositoryMock = new Mock<IPostRepository>(); 
repositoryMock.Setup(r => r.GetMostRecentPosts(1)) 
    .Returns(Enumerable.Empty<Post>()); 
var controller = new BlogController(repositoryMock.Object); 
var result = (ViewResult)controller.Index(1); 
Assert.IsFalse(string.IsNullOrEmpty(result.Model.Message)); 

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

+0

यह बढ़िया है। सहायता के लिए धन्यवाद। मेरे पास थोड़ी देर के लिए मेरे दिमाग के पीछे एक समान मॉडल (डीआई) था लेकिन मैं अभी भी एमवीसी के इंस-आउट-आउट सीख रहा था। मुझे लगता है कि यह समय है कि मैं वापस जाता हूं और अधिक टिकाऊ नियंत्रकों के लिए निर्माण करता हूं। बहुत बहुत धन्यवाद। – BZink

+2

आप कन्स्ट्रक्टर को तर्क कैसे भेजेंगे? मैं यह वही कर रहा हूं, सिवाय इसके कि कन्स्ट्रक्टर में मेरे पास केवल 'myRepository = new MyRepository() 'है। – Cody

+0

@ डॉक्टर ऑरियो: जैसा कि मैंने पोस्ट में कहा था, एमवीसी आपको नियंत्रक फैक्ट्री निर्दिष्ट करने की अनुमति देता है। आप एक नियंत्रक फैक्ट्री बना सकते हैं जो आपके नियंत्रक को बनाते समय भंडार में पास करना जानता है। या आप एक मौजूदा निर्भरता-इंजेक्शन ढांचे का उपयोग कर सकते हैं, भंडार की बाइंडिंग सेट अप कर सकते हैं, और एमवीसी नियंत्रक बनाने के लिए डी ढांचे से पूछता है। – StriplingWarrior

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