Add a DbProviderFactory without an App.Config
Solution 1
The following will probably cause sunspots and overthrow western civilization. It may even cause a debate about Duct Tape Programming (make it stop!), but it works (for now)
try
{
var dataSet = ConfigurationManager.GetSection("system.data") as System.Data.DataSet;
dataSet.Tables[0].Rows.Add("SQLite Data Provider"
, ".Net Framework Data Provider for SQLite"
, "System.Data.SQLite"
, "System.Data.SQLite.SQLiteFactory, System.Data.SQLite");
}
catch (System.Data.ConstraintException) { }
Solution 2
JoshRivers above posted a solution for SQLite. This can in fact be used for other adapters as well- I was able to get it working for MySQL using his example. I have wrapped this into something a bit more generic. This should be run once the application starts and is for the .NET connector version 6.6.5.0 (but I imagine it is good for other versions as well.)
string dataProvider = @"MySql.Data.MySqlClient";
string dataProviderDescription = @".Net Framework Data Provider for MySQL";
string dataProviderName = @"MySQL Data Provider";
string dataProviderType = @"MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.6.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d";
bool addProvider = true;
var dataSet = ConfigurationManager.GetSection("system.data") as DataSet;
foreach (DataRow row in dataSet.Tables[0].Rows)
{
if ((row["InvariantName"] as string) == dataProvider)
{
// it is already in the config, no need to add.
addProvider = false;
break;
}
}
if (addProvider)
dataSet.Tables[0].Rows.Add(dataProviderName, dataProviderDescription, dataProvider, dataProviderType);
Solution 3
LATE ANSWER:
You can always directly get a factory like this:
DbProviderFactory factory = System.Data.SQLite.SQLiteFactory.Instance;
// (note that the rest of the code is still provider-agnostic.)
Or use your IoC container to resolve the DbProviderFactory
, e.g.:
container.RegisterInstance<DbProviderFactory>(SQLiteFactory.Instance);
I prefer not to use the DbProviderFactories.GetFactory
because of its limitation of requiring a configuration file (or a hack like in @JoshRiver's answer).
All DbProviderFactories.GetFactory
does is, it looks up the registered assembly-qualified name of the factory type using the provider name, and then it gets the value of the static Instance
property using reflection.
If you don't want to use the configuration, one of the methods above might be more convenient depending on your use case.
Solution 4
Update for EF 6.0+
You can add a DbProviderFactory
by registering a IDbDependencyResolver
and resolving for the type DbProviderFactory
. An example of this is below:
static class Program
{
[STAThread]
static void Main()
{
System.Data.Entity.DbConfiguration.Loaded += (_, a) => {
a.AddDependencyResolver(new MyDependencyResolver(), true);
};
Application.Run(new Form1());
}
}
class MyDependencyResolver : System.Data.Entity.Infrastructure.DependencyResolution.IDbDependencyResolver {
public object GetService(Type type, object key) {
// Output the service attempting to be resolved along with it's key
System.Diagnostics.Debug.WriteLine(string.Format("MyDependencyResolver.GetService({0}, {1})", type.Name, key == null ? "" : key.ToString()));
if (type == typeof(System.Data.Common.DbProviderFactory)) {
// Return whatever DbProviderFactory is relevant
return new MyDbProviderFactory();
}else if(type == typeof(System.Data.Entity.Infrastructure.IProviderInvariantName) && key != null && key == "MyDbProviderFactory"){
// Return the Provider's invariant name for the MyDbProviderFactory
return new MyProviderInvariantName();
}
return null;
}
public IEnumerable<object> GetServices(Type type, object key) {
return new object[] { GetService(type, key) }.ToList().Where(o => o != null);
}
}
you may have to resolve for some additional types as well depending upon what type of overriding you're needing to do and how your project is setup. Basically just start with the code above and continue to debug until you've determined all the services you need to resolve for given your specific requirements.
You can read more about EF dependency resolution at the links below:
- http://msdn.microsoft.com/en-us/data/jj680697.aspx
- https://entityframework.codeplex.com/wikipage?title=EF%20Configuration%20and%20Extensibility
- https://entityframework.codeplex.com/wikipage?title=Rebuilding%20EF%20providers%20for%20EF6
Additionally, you can do this configuration by overriding DbConfiguration
as described in the first link above.
Solution 5
In .NET Core 2.1 and later you can use DbProviderFactories.RegisterFactory
to programmatically register a DbProviderFactory
.
JasonRShaver
Senior Program Manager at Microsoft I have worked on the following in some way: Silverlight v4, v5 Silverlight Toolkit Windows Phone 7.5 (Mango+Tango) Windows Phone 8 (Apollo) Windows 8 XAML Windows 8.1 (Blue) XAML Windows Phone 8.1 (Blue) XAML Windows 10 XAML Windows 10 AU (Redstone) XAML Visual FoxPro Visual Studio 2015 (Dev14) Azure tooling Microsoft Storage Explorer Visual Studio 2016 (Dev15) Azure tooling Azure XPlat CLI Azure CLI 2.0 Azure CLI Shell @JasonRShaver
Updated on May 06, 2020Comments
-
JasonRShaver about 4 years
I am using DbProviderFactories in my data layer (based on Entity Framework) and am using SQLite for my database, but I don't have to have a App.Config to have the following code:
<configuration> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite"/> <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /> </DbProviderFactories> </system.data> </configuration>
Instead I would like to have my data layer put that in programmatically. Anyone know a way to do this?
EDIT:
The reason for this is that I am using a IoC container to pick the data layer and some of my data layers don't need the App.Config values, or have them be hard tied to the data layer.
-
JasonRShaver over 14 yearsHehe, it works. Not pretty, but it is the only thing out there. Thanks!
-
John Reynolds almost 13 yearsActually, it's quite useful when your app.config is not being read, which is the case when you use F# interactive.
-
Andrus over 3 yearsRegisterFactory does not exist in .NET 5 for unknown reason. I posted it in stackoverflow.com/questions/65465068/…