user610217
user610217

Reputation:

Choose the proper DbProviderFactory in .NET Core?

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

Answers (1)

Parrish Husband
Parrish Husband

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

Related Questions