2010-04-21 58 views
5

我將我的linq封裝到在我的重載控制器的構造函數中實例化的存儲庫類中的sql調用。我的存儲庫類的構造函數創建數據上下文,以便在頁面加載的整個過程中只使用一個數據上下文。即使我明確處理DataContext,爲什麼我的連接沒有關閉?

在我的存儲庫類的析構函數中,我顯式調用了DataContext的處理,儘管我不認爲這是必要的。

使用性能監視器時,如果我看我的用戶連接數並重復加載頁面,則每頁加載次數會增加一次。連接不會關閉或重用(約20分鐘)。

我試着把Pooling = false放在我的配置中,看看這是否有效果,但沒有。在任何情況下,我都不希望每個負載都有一個新的連接,我希望它能夠重用連接。

我試着在析構函數中放置一個斷點,以確保處置正在被擊中,並且確實已經足夠了。那麼發生了什麼?

一些代碼來說明我上面說:

控制器:

public class MyController : Controller 
{ 
    protected MyRepository rep; 

    public MyController() 
    { 
     rep = new MyRepository(); 
    } 
} 

存儲庫:

public class MyRepository 
{ 
    protected MyDataContext dc; 

    public MyRepository() 
    { 
     dc = getDC(); 
    } 

    ~MyRepository() 
    { 
     if (dc != null) 
     { 
      //if (dc.Connection.State != System.Data.ConnectionState.Closed) 
      //{ 
      // dc.Connection.Close(); 
      //} 
      dc.Dispose(); 
     } 
    } 

    // etc 
} 

注:我添加了一些提示和上下文信息的DC用於審計目的。這基本上就是爲什麼我想每個頁面加載一個連接

更新: 已經實現了IDisposable在我的倉庫,並在我的控制器類我無法找到一個方法來專門調用Dispose方法我的控制器作爲後上控制器由MvcHandler在幕後創建和銷燬。不過,我確實發現我的聯繫無論如何都被關閉了。我不舒服知道這是工作,但不知道爲什麼,所以我做了一些挖掘,發現了一個MSDN的報價,讓我開心:

當執行完成後,將MvcHandler如果控制器實現IDisposable檢查界面,如果是的話,將調用控制器上的Dispose來清理非託管資源。

最後更新: 一個月左右的時間與工作這個現在我已經刪除了所有這些代碼,並走了下來MS勸我在公共倉庫方法纏繞在代碼中的「使用」聲明的路線後並將這個DC傳遞給私有方法。這看起來有點浪費和重複,並導致更多的連接被打開和關閉。但我得到的LINQ到SQL緩存,我只能通過重置DC來解決。

回答

4

正確的模式(簡短但足夠的版本)在這裏是:

public class MyRepository : IDisposable 
{ 
    ... // everything except the dtor 

    public void Dispose() 
    { 
     if (dc != null) 
     { 
      dc.Dispose(); 
     } 
    } 
} 

public class MyController : Controller, IDisposable 
{ 
    protected MyRepository rep; 

    public MyController() 
    { 
     rep = new MyRepository(); 
    } 

    public void Dispose() 
    { 
     if (rep!= null) 
     { 
      rep.Dispose(); 
     } 
    } 
} 

現在你可以(應該)使用與myController的所使用的子句:

using (var ctl = new MyController()) 
{ 
    // use ctl 
} 

編輯:
只注意到它級聯到myController的,代碼添加。這顯示了非託管資源的間接所有權如何分散。

編輯2:
這也是正確的(如將是一個try /終於):

var ctl = GetController(); 
using (ctl) 
{ 
    // use ctl 
} 

如果你不能保持它的地方到1點的方法,只是做你最好打電話CTL .Dispose()在關閉事件或類似事件中。

+0

啊,謝謝。我只是想知道我的代碼是否需要添加(指編輯) – 2010-04-21 20:22:18

+0

我不太確定最後一點。 MVC生成我的控制器,那麼我該如何確保它被正確處理? – 2010-04-21 20:26:56

+0

@Chris,繼承時要小心,我注意到你使這些字段受到保護。我不會有。 – 2010-04-21 20:31:02

2

析構函數只能由GC調用。你的MyRepository應該實現Dispose模式,並在那裏處置dc。

看到這個問題的更多細節。 In C# what is the difference between a destructor and a Finalize method in a class?

MyRepository應該實現IDisposable,任何可丟棄的對象都應該放在那裏,如果你在對象的生命週期中持有它們。

很多時候你使用的是一次性的對象的時候,你應該把它包在使用塊

using(var dc = getDC()) 
{ 
    //do stuff with the dc 
}//the dc will be Disposed here 

編輯:鏈接到語言指南C#析構函數 http://msdn.microsoft.com/en-us/library/66x5fx1b(v=VS.100).aspx

+0

而__not__實現析構函數。它在這堂課沒有任何用處。 – 2010-04-21 20:05:09

+0

啊,你是說Dispose不應該在析構函數中調用嗎? – 2010-04-21 20:05:43

+0

約定的析構函數應該在c#應用程序中很少使用。 – 2010-04-21 20:08:18

0

我同意這樣的事實,一次性碎片是不正確的,Henk HoltermanDarryl Braaten以上的建議是非常好的,我不認爲它回答您的根本問題。

您的問題的答案是調用Dispose MyRepository(假設它的DataContext)不會關閉連接。它只是將連接返回到池以備下次使用。

This SO Post,說明了當你應該擔心關閉連接...

+0

原來的問題已經解決了池化問題(「連接沒有關閉或重新使用...」) – 2010-04-21 20:59:17

+0

請問您可以重新說明一下嗎?我不跟? – Nix 2010-04-21 21:05:15

+0

它看起來不像連接正在返回到池中。無論是打開還是關閉池總是會創建新的連接,而不是重新使用 – 2010-04-21 21:29:17

相關問題