हमारे वेब अनुप्रयोगों में हमारे डेटाबेस में विभिन्न प्रकार की तालिकाओं से डेटा की आवश्यकता के लिए यह बहुत आम है। आज आपको एक अनुरोध के लिए 5 या 6 डेटाबेस प्रश्नों को क्रमशः निष्पादित किया जा सकता है। इनमें से कोई भी प्रश्न दूसरे से डेटा पर निर्भर नहीं है, इसलिए वे समानांतर में निष्पादित होने के लिए पूर्ण उम्मीदवार हैं। समस्या DbConcurrencyException
अच्छी तरह से ज्ञात है जिसे उसी संदर्भ के विरुद्ध कई प्रश्न निष्पादित किए जाने पर फेंक दिया जाता है।समांतरता और इकाई फ्रेमवर्क
हम आम तौर पर प्रति अनुरोध एक संदर्भ का उपयोग करते हैं और उसके बाद एक भंडार वर्ग है ताकि हम विभिन्न परियोजनाओं में प्रश्नों का पुन: उपयोग कर सकें। जब हम नियंत्रक का निपटारा करते हैं तो हम अनुरोध के अंत में संदर्भ का निपटान करते हैं।
नीचे एक उदाहरण है जो समांतरता का उपयोग करता है, लेकिन अभी भी एक समस्या है!
var fileTask = new Repository().GetFile(id);
var filesTask = new Repository().GetAllFiles();
var productsTask = AllProducts();
var versionsTask = new Repository().GetVersions();
var termsTask = new Repository().GetTerms();
await Task.WhenAll(fileTask, filesTask, productsTask, versionsTask, termsTask);
प्रत्येक भंडार आंतरिक रूप से अपने स्वयं के संदर्भ पैदा कर रही है, लेकिन जैसा कि अभी है, वे निपटारा नहीं किया जा रहा है। ये एक समस्या है। मुझे पता है कि मैं प्रत्येक रिपोजिटरी पर Dispose
पर कॉल कर सकता हूं, लेकिन यह कोड को जल्दी से अव्यवस्थित करना शुरू कर देता है। मैं प्रत्येक क्वेरी के लिए एक रैपर फ़ंक्शन बना सकता हूं जो अपने संदर्भ का उपयोग करता है, लेकिन यह गन्दा लगता है और समस्या के लिए एक दीर्घकालिक समाधान नहीं है।
इस समस्या का समाधान करने का सबसे अच्छा तरीका क्या होगा? मैं क्लाइंट/उपभोक्ता को समांतर में निष्पादित कई प्रश्नों के मामले में प्रत्येक संग्रह/संदर्भ को निपटाने के बारे में चिंता करने की आवश्यकता नहीं है।
मेरे पास अभी एकमात्र विचार है कि कारखाने के पैटर्न के समान दृष्टिकोण का पालन करना है, सिवाय इसके कि मेरे कारखाने को बनाए गए सभी वस्तुओं का ट्रैक रखा जाएगा। एक बार जब मुझे पता चल जाए कि मेरे प्रश्न खत्म हो गए हैं तो कारखाने कारखाने का निपटान कर सकता है और फैक्ट्री आंतरिक रूप से प्रत्येक भंडार/संदर्भ का निपटान कर सकती है।
मैं समानांतरवाद और इकाई की रूपरेखा के आसपास इस तरह के छोटे से चर्चा देख कर हैरान हूँ, इसलिए उम्मीद है कि समुदाय से कुछ अधिक विचारों में आ जाएगा।
संपादित
यहाँ का एक सरल उदाहरण है क्या हमारा भंडार इस तरह दिखता है:
public class Repository : IDisposable {
public Repository() {
this.context = new Context();
this.context.Configuration.LazyLoadingEnabled = false;
}
public async Task<File> GetFile(int id) {
return await this.context.Files.FirstOrDefaultAsync(f => f.Id == id);
}
private bool disposed = false;
protected virtual void Dispose(bool disposing) {
if (!this.disposed) {
if (disposing) {
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
}
जैसा कि आप देख सकते हैं, प्रत्येक भंडार का अपना संदर्भ प्राप्त होता है। इसका मतलब है कि प्रत्येक भंडार का निपटान करने की आवश्यकता है। उदाहरण में मैंने ऊपर दिया, इसका मतलब है कि मुझे Dispose()
पर 4 कॉल की आवश्यकता होगी।
समस्या का कारखाना दृष्टिकोण के लिए मेरे विचार की तरह कुछ था निम्नलिखित:
public class RepositoryFactory : IDisposable {
private List<IRepository> repositories;
public RepositoryFactory() {
this.repositories = new List<IRepository>();
}
public IRepository CreateRepository() {
var repo = new Repository();
this.repositories.Add(repo);
return repo;
}
#region Dispose
private bool disposed = false;
protected virtual void Dispose(bool disposing) {
if (!this.disposed) {
if (disposing) {
foreach (var repo in repositories) {
repo.Dispose();
}
}
}
this.disposed = true;
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
इस कारखाने मेरी भंडार के उदाहरण बनाने के लिए जिम्मेदार हो सकता है, लेकिन यह भी सभी उदाहरणों यह है का ट्रैक रखने होगा बनाया था। एक बार यह एकल कारखाना वर्ग का निपटारा हो जाने पर यह आंतरिक रूप से बनाए गए प्रत्येक भंडार का निपटान करने के लिए जिम्मेदार होगा।
मेरा मानना है कि यदि आप मैन्युअल रूप से कनेक्शन का प्रबंधन नहीं करते हैं तो एक ईएफ संदर्भ को निपटाने की आवश्यकता नहीं है। इसे प्रत्येक अनुरोध के लिए खोलना और बंद करना चाहिए। संदर्भों का निपटारा नहीं करना मुझे एक गंदे दृष्टिकोण के रूप में हमला करता है, हालांकि। – usr
@usr हमारे पास उत्पादन में किसी और द्वारा लिखा गया कोड है जो सभी संदर्भों का निपटारा नहीं कर रहा है। :) यह काम करता है, लेकिन मैं निश्चित नहीं हूं कि परिणाम क्या हैं या होंगे। चूंकि संदर्भ 'आईडीस्पोजेबल' लागू करता है, इसलिए मैं एक दृष्टिकोण विकसित करना चाहता हूं जो कि क्या हो सकता है के रहस्य को हटा देता है। –
_ "इस समस्या को हल करने का सबसे अच्छा तरीका क्या होगा?" _ - मुझे लगता है कि आपको पहले से पहचाने गए संभावित दृष्टिकोणों पर आपके आपत्तियों के बारे में अधिक विशिष्ट होना चाहिए। "गन्दा" और "अव्यवस्था" से कुछ बेहतर है। तथ्य यह है कि, "गन्दा" और "अव्यवस्था" छिपाने के लिए encapsulation एक आम और वैध तकनीक है, और कुछ प्रकार का एक रैपर encapsulation का एक रूप है। अधिक जानकारी के बिना, आप जो भी प्राप्त करने जा रहे हैं वे अस्पष्ट, राय वाले उत्तर हैं। –