2009-03-07 17 views
5

भंडार से डेटा (मामले के मामले में कस्टम केस) वापस करने का अनुशंसित तरीका क्या है जो किसी भी मॉडल इकाइयों में फिट नहीं होता है या जो कुछ बढ़ाता है?विज्ञापन डेटा और भंडार पैटर्न

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

कुछ यादृच्छिक विचार:

  1. प्रत्येक मॉडल है जो कस्टम डेटा की आबादी किया जा सकता है के लिए संपत्तियों की एक सूची जोड़ें।

  2. सबक्लास मॉडल इकाइयों मामले के मामले में, और प्रत्येक उपclass के लिए कस्टम पाठक बनाते हैं।

  3. LINQ का उपयोग करें, इस तरह के प्रश्न लिखें और अनाम कक्षाएं पढ़ें।

नोट: मैं एक similar question recently पूछा है, लेकिन यह बहुत सामान्य लग रहा था और बहुत ध्यान आकर्षित नहीं किया।

उदाहरण:

जवाब नीचे, मैं एक और अधिक ठोस उदाहरण द्वारा जोड़ा जा रहा में दिए गए सुझावों के आधार पर। यहाँ है स्थिति मैं वर्णन करने के लिए कोशिश कर रहा था:

IEnumarable<Post> posts = repository.GetPostsByPage(1); 
foreach (Post post in posts) 
{ 

    // snip: push post title, content, etc. to view 

    // determine the post count and latest comment date 
    int commentCount = post.Comments.Count(); 
    DateTime newestCommentDate = post.Comments.Max(c => c.Date); 

    // snip: push the count and date to view 

} 

मैं कुछ भी अतिरिक्त नहीं करते हैं और शेल्फ ORM बंद एक का उपयोग करें, यह n + 1 प्रश्नों का परिणाम या जाएगा संभवतः सभी पोस्ट और टिप्पणियों को एक क्वेरी लोड हो रहा है । लेकिन सबसे अच्छा, मैं सिर्फ एक एसक्यूएल निष्पादित करने में सक्षम होना चाहता हूं जो पोस्ट पोस्ट, बॉडी इत्यादि सहित प्रत्येक पोस्ट के लिए एक पंक्ति लौटाएगा और टिप्पणी गिनती और इसमें हाल ही की टिप्पणी की तारीख होगी। यह एसक्यूएल में छोटा है। समस्या यह है कि मेरा भंडार मॉडल में इस प्रकार के डेटा को पढ़ने और फिट करने में सक्षम नहीं होगा। अधिकतम तिथियां कहां और मायने रखती हैं?

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

उत्तर

0

कह सकते हैं न मैं वास्तव में देखने कि समस्या क्या है, बस हवा यहाँ में फायरिंग:

  • जानकारी संपुटित करने के लिए एक विशेष इकाई जोड़े यो चाहते
  • पोस्ट करने के लिए एक संपत्ति टिप्पणियां जोड़ें।(मैं नहीं दिख रहा है यही कारण है कि यह सब टिप्पणियां प्राप्त करने की आवश्यकता होगी - तुम सिर्फ विशेष पोस्ट को आप लोड कर रहे हैं के लिए टिप्पणियां प्राप्त नहीं कर सकते हैं) केवल करने के लिए
  • उपयोग आलसी लोड हो रहा है जब आप संपत्ति का उपयोग टिप्पणियां प्राप्त

मुझे लगता है कि यदि आप प्लेटफॉर्म, भाषा और ओ/आर मैपर विशिष्ट (ऐसा लगता है कि .NET C# या VB जैसा लगता है, तो LINQ 2 SQL? इकाई फ्रेमवर्क का उल्लेख करते हुए आपको अपने प्रश्न का उत्तर देने का अधिक मौका मिलेगा? कुछ और?)

+0

मुझे इंगित करने के लिए धन्यवाद। मैंने एक सरल ठोस उदाहरण और अधिक स्पष्टीकरण जोड़ा है। –

1

इस सवाल के लिए बहुत कुछ है। क्या आपको रिपोर्टिंग प्रक्रिया के लिए इस विशिष्ट डेटा की आवश्यकता है? यदि ऐसा है, तो उचित समाधान रिपोर्टिंग उद्देश्यों के लिए अलग डेटा पहुंच होना है। Flattened डेटाबेस, विचार, ect।

या क्या यह एक विज्ञापन-प्रसार की आवश्यकता है? यदि हां, तो इस समस्या पर आयुर्वे के पास एक पोस्ट है। http://ayende.com/Blog/archive/2006/12/07/ComplexSearchingQueryingWithNHibernate.aspx

वह "फाइंडर" ऑब्जेक्ट का उपयोग करता है। वह NHibernate का उपयोग कर रहा है, इसलिए अनिवार्य रूप से वह क्या कर रहा है एक अलग क्वेरी बना रहा है।

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

क्वेरी वस्तु एक धाराप्रवाह इंटरफ़ेस लागू करता है, इसलिए मैं इस बारे में और परिणामों को वापस प्राप्त कर सकते हैं:

IQuery query = new PostQuery() 
    .WithPostId(postId) 
    .And() 
    .WithCommentCount() 
    .And() 
    .WithCommentsHavingDateLessThan(selectedDate); 


Post post = _repository.Find(query); 

हालांकि, अपने विशिष्ट मामले में मैं अपने डिजाइन पर आश्चर्य है। आप कह रहे हैं कि आप पोस्ट के साथ टिप्पणियां लोड नहीं कर सकते हैं। क्यूं कर? क्या आप प्रदर्शन के बारे में बेहद चिंतित हैं? क्या यह समयपूर्व अनुकूलन का मामला है? (मुझे ऐसा लगता है)

यदि मेरे पास पोस्ट ऑब्जेक्ट था तो यह मेरी कुल रूट होगी और यह टिप्पणियों से जुड़ी होगी। और फिर आप जो भी करना चाहते हैं वह हर परिदृश्य में काम करेगा।

+0

धन्यवाद। आप सुझाव अच्छी शुरुआत की तरह लगते हैं। मुझे आश्चर्य है कि आप वास्तव में टिप्पणी की गणना कहां जमा करते हैं? निश्चित रूप से, पोस्ट इकाई में इसके लिए कोई अलग डेटा सदस्य नहीं है। –

+0

प्रदर्शन के संबंध में, ब्लॉग पोस्ट के साथ उदाहरण सिर्फ एक उदाहरण था। मेरे पास जो वास्तविक अनुप्रयोग है, वह पहले से चल रहा है, और हम वास्तव में पूरे संग्रह को लोड नहीं कर सकते हैं। –

+0

वास्तविक समस्या डोमेन एक फर्क पड़ता है। किसी के लिए यह बताना असंभव है कि क्या आपके पास अपने डोमेन के साथ डिज़ाइन दोष है, जो वास्तव में बेहतर समाधान का कारण बन सकता है। पोस्ट और टिप्पणियां एक हल समस्या है, और आपके प्रश्न प्रासंगिक अर्थ नहीं बनाते हैं। –

1

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

+0

मुझे लगता है कि दूसरा विकल्प संस्थाओं को कुछ नामित प्रश्नों को जोड़ रहा होगा और रिपोजिटरी में उन लोगों का उपयोग करेगा। दिलचस्प सवाल हालांकि, बहुत बुरा था, इसलिए बहुत कम लोग इसे समझने लगते थे। – wds

0

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

0

इसके लिए मेरे पास आम तौर पर एक रिपोजिटरीस्टैटस और एक स्टेटस क्लास होता है जो मेरे डेटा ट्रांसफर ऑब्जेक्ट (डीटीओ) के रूप में कार्य करता है। स्टेटस क्लास का उपयोग मेरी एप्लिकेशन सर्विस लेयर (उसी कारण से) में किया जाता है, जिससे रिपोजिटरीस्टैटस विरासत में आता है। फिर इस वर्ग के साथ मैं रिपोजिटरी परत से त्रुटि संदेश, प्रतिक्रिया वस्तुओं, आदि वापस कर सकते हैं। यह वर्ग सामान्य है कि यह किसी ऑब्जेक्ट को स्वीकार करेगा और इसे रिसीवर के लिए बाहर निकाल देगा।

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using RanchBuddy.Core.Domain; 
using StructureMap; 

namespace RanchBuddy.Core.Services.Impl 
{ 
    [Pluggable("Default")] 
    public class Status : IStatus 
    { 
     public Status() 
     { 
      _messages = new List<string>(); 
      _violations = new List<RuleViolation>(); 
     } 

     public enum StatusTypes 
     { 
      Success, 
      Failure 
     } 

     private object _object; 
     public T GetObject<T>() 
     { 
      return (T)_object; 
     } 
     public void SetObject<T>(T Object) 
     { 
      _object = Object; 
     } 

     private List<string> _messages; 
     public void AddMessage(string Message) 
     { 
      _messages.Add(Message); 
     } 
     public List<string> GetMessages() 
     { 
      return _messages; 
     } 
     public void AddMessages(List<string> Messages) 
     { 
      _messages.AddRange(Messages); 
     } 

     private List<RuleViolation> _violations; 
     public void AddRuleViolation(RuleViolation violation) 
     { 
      _violations.Add(violation); 
     } 
     public void AddRuleViolations(List<RuleViolation> violations) 
     { 
      _violations.AddRange(violations); 
     } 
     public List<RuleViolation> GetRuleViolations() 
     { 
      return _violations; 
     } 
     public StatusTypes StatusType { get; set; } 
    } 
} 

यहाँ और है RepositoryStatus:

यहाँ स्थिति वर्ग है

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using RanchBuddy.Core.Services.Impl; 
using StructureMap; 

namespace RanchBuddy.Core.DataAccess.Impl 
{ 
    [Pluggable("DefaultRepositoryStatus")] 
    public class RepositoryStatus : Status, IRepositoryStatus 
    { 

    } 
} 

आप देख सकते हैं RepositoryStatus अभी तक कुछ भी विशेष नहीं करता है और सिर्फ स्थिति वस्तुओं पर निर्भर करता है के रूप में उपयोगिताओं। लेकिन मैं बाद की तारीख में विस्तार करने का अधिकार आरक्षित करना चाहता था!

मुझे यकीन है कि वहां से कुछ मरने वाले कठोर परिस्थितियों में यह कहा जाएगा कि यदि आप प्रूइस्ट बनना चाहते हैं तो इसका उपयोग नहीं किया जाना चाहिए ... हालांकि मुझे आपका दर्द पता है कि कभी-कभी आपको बस से अधिक गुजरना पड़ता है एक लौटा वस्तु!

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