Reputation:
I have a .net core library that needs a DbProviderFactory
passed into a service as a dependency. It should be SQL Server for the foreseeable future, so I thought I could do something like this:
services.AddSingleton<IMyService>(di=>new MyService(SqlClientFactory.Instance));
... but I have multiple db connection strings in my appsettings.json file, and I don't see a mechanism to tell the Instance
which connection to use.
How do I configure the DbProviderFactory
to use the proper connection and connection string? There's no concept of a "name" for a connection or provider in the appsettings file.
Upvotes: 5
Views: 11152
Reputation: 3178
The connection string settings from the config has a place a provider property. You can use it as follows given the right providers are configured locally:
[System.Configuration.ConfigurationProperty("providerName", DefaultValue=Mono.Cecil.CustomAttributeArgument)] public string ProviderName { get; set; }
<connectionStrings>
<add name="Example"
providerName="System.Data.SqlClient"
connectionString="Data Source=1.1.1.1;Integrated Security=True"/>
</connectionStrings>
Which can be called like so:
DbProviderFactories.GetFactory(settings.ProviderName);
Normally if all you have is a DBConnection, you can create a helper method to retrieve the ProviderFactory:
public static DbProviderFactory GetProviderFactory(DbConnection connection)
{
DbProviderFactory providerFactory = null;
Type connectionType = connection.GetType();
BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
// Check for DbConnection.DbProviderFactory
PropertyInfo providerFactoryInfo = connectionType.GetProperty("DbProviderFactory", flags);
if (providerFactoryInfo != null)
providerFactory = (DbProviderFactory)providerFactoryInfo.GetValue(connection, null);
// Check for DbConnection.ConnectionFactory.ProviderFactory
if (providerFactory == null)
{
PropertyInfo connectionFactoryInfo = connectionType.GetProperty("ConnectionFactory", flags);
object connectionFactory = connectionFactoryInfo.GetValue(connection, null);
providerFactoryInfo = connectionFactory.GetType().GetProperty("ProviderFactory", flags);
providerFactory = (DbProviderFactory)providerFactoryInfo.GetValue(connectionFactory, null);
}
// No match
if (providerFactory == null)
throw new InvalidOperationException("ProviderFactory not found for connection");
return providerFactory;
}
However .NET core doesn't include reflection, so this won't work out of the box.
Upvotes: 3