Is this the right way to dispose the SQLConnection

前端 未结 3 1641
盖世英雄少女心
盖世英雄少女心 2021-01-11 13:17

I was wondering if my below implementation is the most efficient way to dispose the SQLconnection in this case.

I know normally if i\'m using the SqlConnection dire

相关标签:
3条回答
  • 2021-01-11 13:25

    If you want to do it like that, ensure you implement IDisposable (I cant tell if you note this on your IRepository interface or not) and I'll do something like:

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

    Obviously the _context here is your SqlConnection.

    however - are you sure you want one connection per repository? What about operations spanning more than one repository?

    0 讨论(0)
  • 2021-01-11 13:41

    Don't keep the connection open spanning calls. You're defeating connection pooling.

    If you're working with a connection that's pooled (like sqlserver), it will pool and reuse. Just open and close within method a & b.

    You could argue that if the caller does what you did with using with one method call it's fine. But if you do using {} with sqlconnection inside each worker method (1) the code will be simpler and (2) you're ensured the pooling wont be defeated (meaning your holding items out of the pooling when other requests could use it).

    EDIT:

    Adding pseudo based on comments.

    The pattern is problematic because a caller can do.

    //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.
    

    That will kill the scalability of the server - trust me. I've seen very large systems get choked by this - usually because they're spanning AT side transactions.

    A better pattern:

    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.  
            }
        }
    

    Now, the pool is most effective. I realize the question was on the disposable pattern - and yes you can do it. But ...

    I would not let the connection span the lifetime of the repository.

    0 讨论(0)
  • 2021-01-11 13:41

    Assuming IRepository inherits from IDisposable, your implementation is fine provided you are not keeping an instance of your SqlRepository class open for longer than it takes to perform a 'logical' sequence of queries on the database. The fact that this sequence might span several method calls is not a problem.

    I disagree with @bryanmac's answer:

    Don't keep the connection open spanning calls. You're defeating connection pooling.

    Provided your sequence of method calls belong together, and you don't keep the connection open for longer than it takes to complete the logical sequence, I don't see how this in any way defeats connection pooling.

    One comment though. You should:

    • Either implement the standard IDisposable pattern (with a protected void Dispose(bool disposing) method that can be overridden in derived classes

    • Or make your class sealed, in which case your existing IDisposable implementation is fine.

    0 讨论(0)
提交回复
热议问题