Custom db provider factory while maintaining usage of SqlDatabase

Topics: Data Access Application Block
Nov 2, 2011 at 9:52 PM

I need to use a custom db provider factory (it wraps System.Data.SqlClient but adds some additional logging) in .net 3.5 I could just register it under the System.Data.SqlClient name but specify a different type. .net 4 doesn't allow this. However if I name the provider something different then the data access application block falls back to the GenericDatabase class instead of SqlDatabase and it doesn't support parameter sniffing which is also something I need. Is there a way to work arround this?

Editor
Nov 3, 2011 at 3:28 AM
Edited Nov 5, 2011 at 6:46 AM

Hi Olle,

If the logging you want to do is at the method entry and method exit I'm wondering if you could use call handlers to achieve what you want?

I think I understand what you are trying to do but if I've misinterpreted please feel free to clarify.

Here's how to go about this in code.

First create a custom DB Provider:

public class MySqlClientFactory : DbProviderFactory  
{
    private DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");

    public override DbConnection CreateConnection()
    {
        Console.WriteLine("Enter: " + System.DateTime.Now);
        System.Diagnostics.Trace.TraceWarning("Creating connection");
        DbConnection conn = factory.CreateConnection();
        System.Diagnostics.Trace.TraceWarning("Got connection");
        // do something else

        return conn;
    }
}

Then create a database class that extends Database (we need our own database since Database is abstract and SqlDatabase won't let you specify the DbProviderFactory):

[SqlClientPermission(SecurityAction.Demand)]
public class MySqlDatabase : Database
{
    public MySqlDatabase(string connectionString, DbProviderFactory dbProviderFactory)
        : base(connectionString, dbProviderFactory)
    {
    }

    protected override void DeriveParameters(DbCommand discoveryCommand)
    {
        SqlCommandBuilder.DeriveParameters((SqlCommand)discoveryCommand);
    }
}

Then add MySqlDatabase to the container:

var builder = new ConfigurationSourceBuilder();
builder.ConfigureData(); // Potentially Configure DAAB

var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
var coreExtension = new EnterpriseLibraryCoreExtension(configSource);

IUnityContainer container = new UnityContainer();
container.AddExtension(coreExtension);

var factory = new MySqlClientFactory();

var injectionConstructor = new InjectionConstructor(
    new object[] 
            { 
                ConfigurationManager.ConnectionStrings["MySqlConnectionString"].ConnectionString,
                factory
            }
    );

container.RegisterType<Database, MySqlDatabase>("MySqlDatabase", injectionConstructor);

var configurator = new UnityContainerConfigurator(container);
IServiceLocator locator = new UnityServiceLocator(container);
EnterpriseLibraryContainer.Current = locator;

var db = EnterpriseLibraryContainer.Current.GetInstance<Database>("MySqlDatabase");

-- 
Randy Levy
Enterprise Library support engineer
entlib.support@live.com

Dec 3, 2013 at 10:15 PM
Hi,

I have my Database object as a dependency object injected from unity. Is there a way i can do this. I tried the same but it always returns the SqlDatabase object.
In my case i cannot directly instantiate var db = EnterpriseLibraryContainer.Current.GetInstance<Database>("MySqlDatabase"); like this.

Any suggestions ?

Thanks,
Madhu
Editor
Dec 5, 2013 at 6:32 AM
@madhuva, can you post more details about your application and what you are trying to achieve including code to replicate your scenario at the new Data Access Application Block site?

Thanks.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Feb 25 at 8:31 AM
Hi,

Can I get a sample project on how we can implement your code?

Thanks,