-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Problem
DbProviderFactories in .NET Framework provides an API to manage DbProviderFactory which configured in machine.config and load that assembly from GAC via reflection
In Corefx, there is no more GAC and machine.config.
Community are asking to have a standard way to manage DbProviderFactory to write provider agnostic code in libraries.
https://github.com/dotnet/corefx/issues/4571
https://github.com/dotnet/corefx/issues/5782
https://msdn.microsoft.com/en-us/library/ms971499.aspx
Proposal
We will bring back DbProviderFactories in CoreFx.
But instead of register/read the configuration from machine.config, we will provide a code based configuration.
This will allow application writer to hook this with any configuration mechanism.
Contract Changes
We will bring back DbProviderFactories.GetFactory functions in V1 contract which will support .Net 4.6.2.
And add "RegisterFactory" functions in V2 contract to support .Net vNext. (version after 4.6.2)
For portability, we will bring "RegisterFactory" into .Net vNext and should work side by side with file config behavior. e.g code based config will override file based config).
Portable library (such as ORM), can start using GetFactory and target it for .Net 4.6.2.
If this library used in .NET 4.6.2 , GetFactory will return factory which defined in machine/app configs.
Corefx application which used this portable library can register their factory using "RegisterFactory".
Once we release "RegisterFactory" into .Net vNext, The behavior will be work seamless in both frameworks.
namespace System.Data.Common
{
public static class DbProviderFactories
{
// V1 -- Supported by .NET Framework 4.6.2 (the upcoming version)
public static DbProviderFactory GetFactory(string providerInvariantName);
public static DbProviderFactory GetFactory(DbConnection connection);
// V2 -- Supported by .NET Core 1.0 and by .NET Framework vNext (version after 4.6.2)
public static void RegisterFactory(string providerInvariantName, DbProviderFactory factory);
public static IEnumerable<string> GetFactoryProviderNames();
}
}DbProviderFactories
CoreFx Implementation
public abstract class DbProviderFactories
{
internal static readonly Dictionary<string, Func<DbProviderFactory>> _configs = new Dictionary<string, Func<DbProviderFactory>>();
public static DbProviderFactory GetFactory(string providerInvariantName)
{
ADP.CheckArgumentLength(providerInvariantName, nameof(providerInvariantName));
if (_configs.ContainsKey(providerInvariantName))
{
return _configs[providerInvariantName]();
}
throw ADP.ConfigProviderNotFound();
}
public static DbProviderFactory GetFactory(DbConnection connection)
{
ADP.CheckArgumentNull(connection, nameof(connection));
return connection.ProviderFactory;
}
public static void RegisterFactory(string providerInvariantName, DbProviderFactory factory) {
ADP.CheckArgumentNull(providerInvariantName, nameof(providerInvariantName));
ADP.CheckArgumentNull(constructorDelegate, nameof(constructorDelegate));
_configs[providerInvariantName] = factory;
}
public static IEnumerable<string> GetFactoryProviderNames() {
return _configs.Keys.toArray();
}
}Usage
For CoreFX application, You need to register your provider factory during startup of your application.
public static void Startup()
{
//SqlClientFactory is a singleton factory
DbProviderFactories.Add("System.Data.SqlClient", SqlClientFactory.Instance);
//You can use other factory which not singleton.
DbProviderFactories.Add("System.Data.OtherProvider", new OtherProviderFactory());
}Progress
I have created initial commit on my branch to inspect what are the changes needed.
kkurni/corefx@68380b3