2010-05-07 18 views
14

मेरे अनुभव निर्माण वेब अनुप्रयोगों में, मैंने हमेशा एक एन-टियर दृष्टिकोण का उपयोग किया है। एक डीएएल जो डीबी से डेटा प्राप्त करता है और ऑब्जेक्ट्स को पॉप्युलेट करता है, और बीएलएल जो डीएएल से वस्तुओं को प्राप्त करता है और उन पर आवश्यक कोई व्यावसायिक तर्क करता है, और वेबसाइट जो बीएलएल से इसका प्रदर्शन डेटा प्राप्त करती है। मैंने हाल ही में LINQ सीखना शुरू कर दिया है, और अधिकांश उदाहरण वेब एप्लिकेशन कोड-बैक से होने वाले प्रश्नों को दिखाते हैं (यह संभव है कि मैंने केवल सरलीकृत उदाहरणों को देखा हो)। एन-स्तरीय आर्किटेक्चर में, इसे हमेशा एक बड़ा नो-नो के रूप में देखा जाता था।
मुझे एक नया वेब एप्लिकेशन आर्किटेक्ट करने के बारे में कुछ अनिश्चितता है। मैं डीएसएमएल और ऑब्जेक्ट रिलेशनशिप बनाने के लिए वीएस 2008 में सर्वर एक्सप्लोरर और डीबीएमएल डिजाइनर का उपयोग कर रहा हूं। यह मुझे थोड़ा अस्पष्ट लगता है अगर डीबीएमएल को डीएएल परत माना जाएगा, यदि वेबसाइट को बीएलएल के भीतर विधियों को कॉल करना चाहिए, जो तब LINQ प्रश्न, आदि करेगा
कुछ सामान्य आर्किटेक्चर सर्वोत्तम प्रथाओं या दृष्टिकोण क्या हैं LINQ से SQL का उपयोग कर एक वेब अनुप्रयोग समाधान बनाना?LINQ से SQL वेब अनुप्रयोग सर्वोत्तम अभ्यास

उत्तर

16

मुझे डर है कि आपने वास्तव में अत्यधिक सरलीकृत उदाहरण देखे हैं। LINQ से SQL (System.Data.Linq) आपकी डीएएल परत है। कक्षाएं एल 2 एस उत्पन्न करती है आपका डोमेन (लेकिन Domain-Driven Design से भ्रमित नहीं है)। इसके शीर्ष पर आप अभी भी अपना बिजनेस लेयर लिख सकते हैं।

मैं प्रस्तुति परत (आपका वेब ऐप) में LINQ को SQL DataContext पर लीक करने से रोकने का प्रयास करता हूं। तो यह DataContext बनाने या प्रतिबद्ध करने में सक्षम नहीं होना चाहिए। प्रस्तुति परत पर आपको IQueryable<T> ऑब्जेक्ट्स वापस नहीं करना चाहिए। आईएमओ व्यापार परत DataContext (काम की इकाई) के जीवनकाल और एसक्यूएल प्रश्नों के आकार पर पूर्ण नियंत्रण होना चाहिए।

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

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

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

इस समस्या को हल करने के लिए, आपको बीएल से प्रस्तुति परत में डेटा ट्रांसफर ऑब्जेक्ट्स (डीटीओ) वापस करना चाहिए। एक डीटीओ में केवल डेटा और नहीं आंतरिक DataContext, और कोई आलसी लोड गुण नहीं होंगे। एक डीटीओ को विशेष रूप से वास्तविक अनुरोध के लिए प्रारूपित किया जा सकता है। डीटीओ निश्चित रूप से कोडिंग ओवरहेड को ले जाते हैं, इसलिए आपके सिस्टम का आकार और प्रदर्शन आवश्यकताओं को इसे उचित ठहराना चाहिए। अपने लिए इसे आसान बनाने के लिए, मैं एक डीटीओ पर स्थिर प्रक्षेपण विधियों को डालता हूं। हालांकि यह separation of concerns सिद्धांत के अनुरूप नहीं है, लेकिन मैंने इसे बहुत व्यावहारिक समाधान माना है। इस CustomerDTO पर उदाहरण के लिए देखो:

public class CustomerDTO 
{ 
    public int CustomerId { get; set; } 
    public string Name { get; set; } 
    // City is flatterned from Address.City. 
    public string City { get; set; } 

    internal static IQueryable<CustomerDTO> AsDTO(IQueryable<Customer> customers) 
    { 
     return 
      from customer in customers 
      select new CustomerDTO() 
      { 
       CustomerId = customer.Id, 
       Name = customer.Name, 
       City = customer.Address.City 
      }; 
    } 
} 

यह डीटीओ एक आंतरिक AsDTO विधि है, जो CustomerDTO DTOs का संग्रह करने के लिए Customer डोमेन वस्तुओं का संग्रह परिवर्तित करने में सक्षम है परिभाषित करता है। इससे डीटीओ को डोमेन ऑब्जेक्ट्स का रूपांतरण बहुत आसान हो जाता है। इस बीएल विधि में उदाहरण के लिए देखो:

public static CustomerDTO[] GetCustomersByCountry(string country) 
{ 
    using (var db = ContextFactory.CreateContext()) 
    { 
     IQueryable<Customer> customers = 
      (from customer in db.Customers 
      where customer.Address.Country == country 
      orderby customer.Name, customer.Id); 

     return CustomerDTO.AsDTO(customers).ToArray(); 
    } 
} 

इस विधि की अच्छी बात यह है कि जब आप SQL क्वेरी को देखो, तो आप देखेंगे कि केवल ग्राहक आईडी, नाम और पता तालिका के शहर होगा डेटाबेस से पुनर्प्राप्त किया जाना चाहिए। ऐसा इसलिए है क्योंकि AsDTO विधि एक IQueryable दूसरे में अनुवाद करती है, जिससे LINQ से SQL को डेटाबेस में कुल ऑपरेशन करने की अनुमति मिलती है।

मुझे उम्मीद है कि यह कुछ विचार बताएगा कि आप क्या कर सकते हैं। बेशक, यह विषय और मेरे परिस्थितियों में व्यावहारिक चीजें जो मैंने पाया है, पर मेरा विचार है।

+0

पूरी प्रतिक्रिया के लिए धन्यवाद। मैं प्रेजेंटेशन परत में डेटा एक्सेस करने पर क्रिंग करता हूं। मैं वर्तमान में डेटलायर में अपनी अधिकांश सॉर्टिंग करता हूं ताकि यह कोई मुद्दा न हो। मैंने पहले डीटीओ के बारे में नहीं सुना है, आगे की ओर देखने के लिए कुछ ऐसा लगता है। – derek

+0

डीटीओ को अक्सर बहुत अधिक ओवरहेड माना जाता है। तार में डेटा भेजते समय वे विशेष रूप से उपयोगी होते हैं (उदाहरण के लिए, जब डब्ल्यूसीएफ या एएसएमएक्स वेब सेवाएं होती हैं)। उदाहरण के लिए, जब आप डिनो एस्पोजिटो के "माइक्रोसॉफ्ट .NET: एंटरप्राइज़ के लिए आर्किटेक्चरिंग एप्लीकेशन" पढ़ते हैं, तो आप देखेंगे कि डिनो सोचता है कि जब आप एक ही ऐपडोमेन की परतों के बीच वस्तुओं को स्थानांतरित कर रहे होते हैं तो वे आमतौर पर अधिक ओवरहेड देते हैं। हालांकि, वह इस बारे में सही है, फिर भी मैंने उन्हें उस विशेष परिदृश्य में उपयोगी पाया और मुझे लगता है कि प्रौद्योगिकी में सुधार होने पर ओवरहेड छोटे हो रहा है ... – Steven

+0

उदाहरण के लिए, नई सी # भाषा संरचनाएं जैसे स्वचालित गुण डीटीओ को परिभाषित करना आसान बनाता है और एक रिफैक्टरिंग उपकरण जैसे रिफैक्टरिंग! प्रो एक LINQ क्वेरी के अंदर एक अनाम प्रकार परिभाषा से स्वचालित रूप से एक डीटीओ उत्पन्न करने की अनुमति देता है। – Steven

4

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

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