I am working on an ASP.NET Core project where I am using SqlCredential
for database authentication, provided by a SqlCredentialProvider
which is designed as a singleton to ensure a single instance throughout the application. Here's how I have set up the DI container and configured the services:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// SqlCredentialProvider is a singleton to provide consistent SqlCredential instances
services.AddSingleton<SqlCredentialProvider>();
// SqlConnection is registered as transient and constructed with SqlCredential
services.AddTransient<SqlConnection>(serviceProvider =>
{
var sqlCredentialProvider = serviceProvider.GetRequiredService<SqlCredentialProvider>();
var sqlCredential = sqlCredentialProvider.GetCredential();
return new SqlConnection("ConnectionString", sqlCredential);
});
// ApplicationDbContext is configured to use the injected SqlConnection
services.AddDbContext<ApplicationDbContext>((serviceProvider, options) =>
{
var sqlConnection = serviceProvider.GetRequiredService<SqlConnection>();
options.UseSqlServer(sqlConnection);
});
}
}
Given this configuration:
- Is this the correct approach to ensure that
SqlConnection
instances, built withSqlCredential
from a singleton provider, are properly managed and disposed of by EF Core? - Are there better practices or patterns to manage
SqlConnection
withSqlCredential
in an ASP.NET Core application using Dependency Injection? I am particularly concerned about the correct disposal ofSqlConnection
to prevent any potential resource leaks. Any advice or guidance would be greatly appreciated.
Here's the original code:
services.AddScoped<SqlCredential>(_ =>
{
//ToSecureString is an extension method for converting a string to a SecureString.
return new SqlCredential("sa", "password".ToSecureString());
});
services.AddScoped(serviceProvider =>
{
var sqlCredentialProvider = serviceProvider.GetRequiredService<SqlCredentialProvider>();
var sqlCredential = sqlCredentialProvider.GetCredential();
return new SqlConnection(configuration.GetConnectionString("MyApplicationConnectionStr"), sqlCredential);
});
// ApplicationDbContext is configured to use the injected SqlConnection
services.AddDbContext<ApplicationDbContext>((serviceProvider, options) =>
{
var sqlConnection = serviceProvider.GetRequiredService<SqlConnection>();
options.UseSqlServer(sqlConnection);
});
During concurrency testing, I noticed that the user connections on the database were exceeding ten thousand, leading me to suspect that SqlConnection
instances were not disposed properly. I then modified the code to the above and now it seems to work fine