簡體   English   中英

這是處理SQLConnection的正確方法嗎?

[英]Is this the right way to dispose the SQLConnection

我想知道在這種情況下我的下面的實現是否是處理SQL連接的最有效方法。

我通常知道如果我直接使用SqlConnection,我可以將連接包裝在一個使用塊中以自動處理它,但在這種情況下,我想保持連接打開並可用於SQLRespository類中的所有方法。

public class SqlRepository : IRepository
{
    private readonly string connectionString;
    private SqlConnection connection;

    public SqlRepository(string connectionString)
    {
        this.connectionString = connectionString;
        connection = new SqlConnection(connectionString);
        connection.Open();
    }

    public void Method_A()
    {
      // uses the SqlConnection to fetch data
    }     

    public void Method_B()
    {
      // uses the SqlConnection to fetch data
    }     

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

用法:

using (IRepository repository = new SqlRepository(connectionString))
{
   var item = repository.items;     
}

更新 IRepository確實實現了IDisposable

不要保持連接打開跨越呼叫。 你正在打敗連接池。

如果您正在使用匯集的連接(如sqlserver),它將進行池化和重用。 只需在方法a和b中打開和關閉即可。

您可以爭辯說,如果調用者使用一種方法執行您所做的操作就可以調用它。 但是如果你在每個工作方法(1)中使用帶有sqlconnection的{},代碼將更簡單,並且(2)你確保池不會被破壞(意味着當其他請求可以使用它時,你可以將池中的項目排除在池外) 。

編輯:

根據評論添加偽。

該模式存在問題,因為呼叫者可以這樣做。

//pseudo code
using (SqlRepository r)
{
    r.MethodA();

    // other code here that takes some time.  your holding a connection
    // out of the pool and being selfish.  other threads could have
    // used your connection before you get a chance to use it again.

    r.MethodB();
}  // freed for others here.

這會破壞服務器的可擴展性 - 相信我。 我已經看到非常大的系統被這種情況所困擾 - 通常是因為它們正在跨越AT側交易。

更好的模式:

class Repository
{
    void MethodA()
    {
        using (Sqlconnection)
        {
             // db call
        }
    }

    void MethodB()
    {
        using (Sqlconnection)
        {
            // you can even have multiple calls here (roundtrips)
            // and start transactions.  although that can be problematic
            // for other reasons.  
        }
    }

現在,游泳池是最有效的。 我意識到問題在於一次性模式 - 是的,你可以做到。 但......

我不會讓連接跨越存儲庫的生命周期。

如果你想這樣做,確保你實現IDisposable(我不能告訴你是否在你的IRepository接口上注意到這一點),我會做類似的事情:


        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);
        }

顯然這里的_context是你的SqlConnection。

但是 - 您確定每個存儲庫需要一個連接嗎? 那些跨越多個存儲庫的操作呢?

假設IRepository繼承自IDisposable ,那么您的實現就可以了,前提是您沒有將SqlRepository類的實例打開的時間超過在數據庫上執行“邏輯”查詢序列所需的時間。 此序列可能跨越多個方法調用的事實不是問題。

我不同意@bryanmac的回答:

不要保持連接打開跨越呼叫。 你正在打敗連接池。

如果您的方法調用序列屬於一起,並且您沒有保持連接打開的時間超過完成邏輯序列所需的時間,我不會看到這會以任何方式阻止連接池。

但有一條評論。 你應該:

  • 實現標准IDisposable模式(帶有protected void Dispose(bool disposing)方法,可以在派生類中重寫)

  • 或者讓你的課程密封,在這種情況下你現有的IDisposable實現是好的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM