2009-08-29 22 views
7
public class TestBL 
{ 
    public static void AddFolder(string folderName) 
    { 
     using (var ts = new TransactionScope()) 
     { 
      using (var dc = new TestDataContext()) 
      { 
       var folder = new Folder { FolderName = folderName }; 

       dc.Folders.InsertOnSubmit(folder); 
       dc.SubmitChanges(); 

       AddFile("test1.xyz", folder.Id); 
       AddFile("test2.xyz", folder.Id); 
       AddFile("test3.xyz", folder.Id); 

       dc.SubmitChanges(); 
      } 

      ts.Complete(); 
     } 
    } 

    public static void AddFile(string filename, int folderId) 
    { 
     using (var dc = new TestDataContext()) 
     { 
      dc.Files.InsertOnSubmit(
       new File { Filename = filename, FolderId = folderId }); 

      dc.SubmitChanges(); 
     } 
    } 
} 

यह नेस्टेड डेटाकॉन्टेक्स्ट (अनचाहे) का एक उदाहरण है। समस्या तब शुरू होती है जब हमारे छोटे प्रयोग (जैसा कि ऊपर दिखाया गया है) में एक ट्रांज़ेक्शनस्कोप जोड़ा जाता है। AddFolder फ़ंक्शन पर पहला AddFile लेनदेन को डीटीसी (जो सभी माध्यमों से खराब है) को बढ़ा देगा, क्योंकि AddFile नए डेटा कॉन्टेक्स्ट को प्रारंभ करता है, इस प्रकार डीबी को दूसरा कनेक्शन खोलता है।बीएल में नेस्टेड डेटाैकेंटेक्स्ट को कैसे संभालें?

  1. मैं नेस्टेड डेटाकॉन्टेक्स्ट का उपयोग कैसे कर सकता हूं जो डीटीसी उपयोग नहीं करेगा?
  2. क्या यह सब सिर्फ सादा गलत है? क्या मुझे डेटाकॉन्टेक्स्ट का अलग-अलग उपयोग करना चाहिए?
+0

दुर्भाग्य से मुझे लगा कि इस प्रश्न को ध्यान में नहीं मिला है और इसका पूरी तरह उत्तर नहीं दिया गया है :( –

उत्तर

3

कोई संदेह नहीं है कि जहां संभव हो वहां डीटीसी से आगे बढ़ना चाहिए। जब मैंने पहली बार अपना प्रश्न पढ़ा, तो मेरे आंत ने कहा कि आपका लेनदेन डीटीसी में नहीं बढ़ेगा क्योंकि आप दोनों डेटा संदर्भों में एक ही कनेक्शन स्ट्रिंग का उपयोग कर रहे हैं। हालांकि, this article के अनुसार, मैं गलत था।

आप डेटा संदर्भों के साथ सर्वोत्तम प्रथाओं पर confusion में अकेले नहीं हैं। यदि आप इसके लिए वेब खोजते हैं, तो पूरे नक्शे में उत्तर हैं। आपके उदाहरण में, आप डेटा संदर्भ को AddFile विधि में पास कर सकते हैं। या, आप इस डेटा को उस वर्ग में एक्सेस कर सकते हैं जो डेटा संदर्भ के जीवनकाल को तब तक बनाए रखता है जब तक फ़ोल्डर और फ़ाइलें सभी सहेजी नहीं जातीं। रिक स्ट्राल ने कई तकनीकों पर an article पोस्ट किया।

फिर भी, LINQ से SQL के आसपास मैंने जो भी जवाब देखा है, वह बहुत संतोषजनक प्रतीत होता है। क्या आपने ओआरएम का उपयोग करके अपनी डेटा परत के प्रबंधन से परहेज किया है? मैंने बड़ी सफलता के साथ NetTiers का उपयोग किया है, लेकिन मैं PLINQO के बारे में अच्छी बातें सुनता हूं। इन दोनों को CodeSmith की आवश्यकता है, लेकिन many alternatives हैं।

+0

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

+0

ऐसा प्रतीत होता है कि ओआरएम बदलना बुद्धिमान समाधान होगा क्योंकि माइक्रोसॉफ्ट एक बहुत ही बुनियादी आपूर्ति प्रदान करता है जो एंटरप्राइज़ जरूरतों के अनुरूप नहीं होगा, इसलिए मैंने एनएचबर्ननेट पर स्विच किया :) –

0

मैं ऐसी परिस्थितियों को संभालने का एक तरीका लेकर आया हूं। एक बीएल इकाई के लिए

नमूना आधार वर्ग

abstract public class TestControllerBase : IDisposable 
{ 
    public TestDataContext CurrentDataContext { get; private set; } 

    protected TestControllerBase() 
    { 
     CurrentDataContext = new TestDataContext(); 
    } 

    protected TestControllerBase(TestDataContext dataContext) 
    { 
     CurrentDataContext = dataContext; 
    } 

    protected void ClearDataContext() 
    { 
     CurrentDataContext.Dispose(); 
     CurrentDataContext = new TestDataContext(); 
    } 

    public void Dispose() 
    { 
     CurrentDataContext.Dispose(); 
    } 
} 

कार्यान्वित नियंत्रक

public sealed class BLTestController : TestControllerBase 
{ 
    public BLTestController() { } 

    public BLTestController(TestDataContext dataContext) 
     : base(dataContext) { } 

    // The entity functions will be implemented here using CurrentDataContext 
} 

एक कार्यान्वित नियंत्रक के सरल उपयोग (इकाई इस वर्ग के वारिस होगा)

var testController = new BLTestControllerA(); 

testController.DeleteById(1); 
एक कार्यान्वित नियंत्रक के

अधिक जटिल उपयोग (समान DataContext पर 2 नियंत्रकों)

var testControllerA = new BLTestControllerA(); 
var testControllerB = new BLTestControllerB(testControllerA.CurrentDataContext); 

testControllerA.DeleteById(1); 
testControllerB.DeleteById(1); 

मैं इस पहेली और इसके बाद के संस्करण कोड के बारे में टिप्पणी को सुलझाने के बारे में और अधिक विचारों देखना चाहते हैं।

0

आपको इस लेनदेन के लिए 2 या अधिक राउंडट्रिप्स करने की आवश्यकता नहीं है। मेरा मानना ​​है कि LINQ-DataContext यह पहचानने के लिए स्मार्ट है कि वे फ़ाइलें फ़ोल्डर ऑब्जेक्ट से संबंधित हैं और फ़ोल्डर पंक्ति को पहले और उसके बाद फाइलें डालेंगी (लेनदेन के संदर्भ में सब कुछ, जैसे BEGIN TRAN/COMMIT)। हालांकि आपको ऐसा करने की ज़रूरत है:

dc.Files.InsertOnSubmit(
       new File { Filename = filename, Folder = folder }); 

फ़ोल्डर आईडी के बजाय।कुछ इस तरह:

public class TestBL 
{ 
    public static void AddFolder(string folderName) 
    { 
     using (var ts = new TransactionScope()) 
     { 
      using (var dc = new TestDataContext()) 
      { 
       var folder = new Folder { FolderName = folderName }; 

       AddFile(dc, "test1.xyz", folder); 
       AddFile(dc, "test2.xyz", folder); 
       AddFile(dc, "test3.xyz", folder); 

       dc.SubmitChanges(); 
      } 

      ts.Complete(); 
     } 
    } 

    private static void AddFile(DataContext dc, string filename, Folder folder) 
    { 
      dc.Files.InsertOnSubmit(
       new File { Filename = filename, Folder = folder }); 
    } 

    public static void AddFile(string filename, int folderId) 
    { 
     using (var dc = new TestDataContext()) 
     { 
      var folder = new Folder { FolderId = folderId }; 
      dc.Attach(folder, false); 
      AddFile(dc, filename, folder); 

      dc.SubmitChanges(); 
     } 
    } 
} 

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

+0

लिंक यहां लेनदेन-स्कोप/डीटीसी रिश्तों को पूरी तरह से समझाया गया है, हालांकि यह मैंने जो पूछा उससे थोड़ा अलग है। –

1

डाटाकॉन्टेक्स्ट को एडफाइल को पैरामीटर के रूप में पास करने के अलावा, आप एक डेटाकॉन्टेक्स्ट कनेक्शन कनेक्शन को किसी अन्य डेटा कॉन्टेक्स्ट में भी पास कर सकते हैं। यह गारंटी देगा कि अन्य डेटाकॉन्टेक्स्ट का एक ही कनेक्शन है।

प्रत्येक डेटाकॉन्टेक्स्ट में एक लेनदेन संपत्ति भी होती है, जिसे आप शायद ट्रांसएक्शनस्कोप ऑब्जेक्ट का उपयोग करने के बजाय सेट और पास कर सकते हैं।

+0

मुझे नहीं लगता कि कनेक्शन संपत्ति को पास करना संभव है, लेकिन हो सकता है कि आप कुछ और मतलब - क्या आप एक कोड उदाहरण जोड़ सकते हैं? –

+0

@Eran: DataContext ऑब्जेक्ट में एक ओवरलोडेड कन्स्ट्रक्टर है जो किसी भी IDbConnection ऑब्जेक्ट को स्वीकार करता है। तो आप नया डेटा कॉन्टेक्स्ट (OldDataContext.Connection) कर सकते हैं – rossisdead

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