Unable to find the requested .Net Framework Data Provider. It may not be installed.

From .Net 2.0 there is an option for you to obtain your dataprovider (usually if using 3rd party providers) by using the DbProviderFactories/ DbProviderFactory classes.

A simple example:

string provider = "System.Data.SqlClient";

DbProviderFactory dbFactory = DbProviderFactories.GetFactory(provider);

Now, every now and then I get cases where the customer reports the following error when doing this:

System.ArgumentException: Unable to find the requested .Net Framework Data Provider. It may not be installed.

   at System.Data.Common.DbProviderFactories.GetFactory(String providerInvariantName)

The reason for getting the error is that it (obviously) is not installed.

But this error will also be thrown if:

.1 The provider is installed but is missing in the

<system.data>

    <DbProviderFactories>

     ...

section in the config files.

.2 The provider is there, but is using an incorrect name. And since incorrect here means that this is case sensitive you would get an error by using "System.Data.Sqlclient" in

the example above. Note the lowercase ‘c’.

A small demo shows this:

        static void Main(string[] args)

        {

            try

            {

                string provider = "System.Data.SqlClient";

                DbProviderFactory dbFactoryUpperCase = DbProviderFactories.GetFactory(provider);

                Console.WriteLine("{0} created...\n", provider);

                // Replace uppercase C with lowercase C

                provider = provider.Replace('C', 'c');

                DbProviderFactory dbFactoryLowerCase = DbProviderFactories.GetFactory(provider);

                Console.WriteLine("{0} created...\n", provider);

            }

            catch (Exception ex)

            {

                Console.WriteLine(ex);

            }

        }

The output:

System.Data.SqlClient created...

System.ArgumentException: Unable to find the requested .Net Framework Data Provider. It may not be installed.

   at System.Data.Common.DbProviderFactories.GetFactory(String providerInvariantName)

   at UnableTo.Program.Main(String[] args) in C:\BlogStuff\UnableTo\UnableTo\Program.cs:line 21

So how does this work?

When the application is started the config files are read (machine.config/app.config and web.config (if it is a web application)) and then merged.

For this scenario, all <system.data><DbProviderFactories> entries in these config files are stored in an internal table in an internal DataSet.

Then what happens is that when you call DbProviderFactories.GetFactory(provider) is that the underlying .Net code gets this DataSet (that is filled with tables related to different settings).

It then checks for the existence of a table called “DbProviderFactories” (like the section in the configuration files).

If this table exists, it calls table.Rows.Find(theProviderName) on that table and if no row is found, the exception is thrown.

If a row is found, then the code calls the overloaded GetFactory(DataRow) method and you are good to go.

To summarize, when you hit the “Unable to find the requested .Net Framework Data Provider” exception make sure that the following is true.

.1 The <system.data><DbProviderFactories> section in machine.config OR app.config OR web.config contains the provider that you wish to load.

.2 The provider name you are sending in to the GetFactory() method is spelt correctly and that it uses the same case.

Finally, if you wish to know what providers that are available for your application, you can query the DataSet/DataTable mentioned above.

Just show that the .config files are merged, we will also add a fake provider to the app.config.

So, create a new .Net console application. Right click the project and add a new app.config file (Add->New Item->Application Configuration File)

In this file (app.config) add the following section in the configuration section:

<configuration>

  <system.data>

    <DbProviderFactories>

      <add name="My Fake Provider" invariant="System.Data.FakeProvider" description="xxx" type="xxx"/>

    </DbProviderFactories>

  </system.data>

</configuration>

Replace the main method so it looks like this:

        static void Main(string[] args)

        {

            try

            {

                System.Data.DataTable dt = System.Data.Common.DbProviderFactories.GetFactoryClasses();

                for (int i = 0; i < dt.Rows.Count; i++)

                    Console.WriteLine("{0}: {1}", i.ToString(), dt.Rows[i][2].ToString());

                Console.WriteLine("------------------------------------------------------\n");

            }

            catch (Exception ex)

            {

                Console.WriteLine(ex);

            }

        }

Output should be:

0: System.Data.Odbc

1: System.Data.OleDb

2: System.Data.OracleClient

3: System.Data.SqlClient

4: System.Data.FakeProvider

The first providers are collected from the machine.config and the FakeProvider is collected from the app.config we just created.

More info here:

".NET Framework Developer's Guide - DbProviderFactories (ADO.NET)"

https://msdn.microsoft.com/en-us/library/wda6c36e.aspx

".NET Framework Developer's Guide - Obtaining a DbProviderFactory (ADO.NET)"

https://msdn.microsoft.com/en-us/library/dd0w4a2z.aspx

".NET Framework Developer's Guide - Configuration Files"

https://msdn.microsoft.com/en-us/library/1xtk877y(VS.71).aspx

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------