Possible memory leak in System.Data.SqlClient when using SqlCredential
See original GitHub issueTested on .NET Core 2.1 with System.Data.SqlClient v4.5.1. Also tested on .NET Framework 4.7.2 with System.Data.SqlClient v4.5.1
When using SqlCredential
to specify credentials for a SqlConnection
there seems to ba a memory leak in some scenarios.
Consider the following program that just repeatedly creates a new SqlConnection
, opens it and then closes it:
using System;
using System.Data.SqlClient;
using System.Security;
namespace MemTest
{
class Program
{
static void Main(string[] args)
{
SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder();
sb.DataSource = ".";
sb.Pooling = false;
string connectionString = sb.ConnectionString;
string password = "XXXX";
using (var securePassword = ToSecureString(password))
{
while (true)
{
SqlCredential cred = new SqlCredential("sa", securePassword);
using (SqlConnection conn = new SqlConnection(connectionString, cred))
{
conn.Open();
}
}
}
}
static SecureString ToSecureString(string str)
{
SecureString s = new SecureString();
foreach (var c in str)
s.AppendChar(c);
s.MakeReadOnly();
return s;
}
}
}
This program does not use connection pooling, but does create a new SqlCredential
instance for each call. The memory usage seems to constantly increase, and using a memory profiler also indicates that memory consumption increases. It also appears that the program slows down over time.
The memory profiler we used seems to indicate among other things that there is a bunch of new instances of SqlConnectionString
held by an SqlConnectionFactory
constantly being allocated without being freed.
The documentation states that using a new instance of an SqlCredential
will cause a new connection rather than using a pooled connection even if the user id and the passwords are the same. So this will obviously cause problems when using pooled connections if a new SqlCredential
instance is used for each connection, but in the case above connection pooling is turned off in the connection string, so why does memory usage seem to increase here?
In our real scenario, we need to use connection pooling, but we also need to be able to indicate that a specified connection/SqlCredential
will no longer be used and should be freed. If we try to use connection pooling, the memory also seems to increase, even if we call SqlConnection.ClearPool(conn)
in the inner loop. How can we forefully remove a connection using a specific SqlCredential
from the pool to avoid this problem?
Issue Analytics
- State:
- Created 5 years ago
- Comments:7 (3 by maintainers)
We have same issue and resolved it by using single instance of SqlCredential object in every SqlConnection, instead of creating SqlCredential object every time.
We were able to reproduce the issue on our end. Currently looking into it.