Registering new Database type in config

Topics: Building and extending application blocks, Data Access Application Block
Nov 10, 2011 at 12:57 PM

I made a custom class which is derived from SqlDatabase, and what it does, is just overrides all Execute... methods to implement some retry logic. How can I tell DatabaseFactory via config that whenever I need a connection to SQL database, it should use my RetrySqlDatabase instead of SqlDatabase?

Nov 11, 2011 at 4:01 AM

The issue with configuring via the regular configuration file is that when the providerName is set to be "System.Data.SqlClient" Enterprise Library (via the DbProviderMapping class) will create a SqlDatabase instead of your RetrySqlDatabase.

One way to get around this is to register your class directly into the container similar to this question.  For your scenario this would look something like:

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 injectionConstructor = new InjectionConstructor(
    new object[] 
            { 
                ConfigurationManager.ConnectionStrings["RetrySqlConnectionString"].ConnectionString,
                System.Data.SqlClient.SqlClientFactory.Instance
            }
    );

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

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

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

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

Nov 11, 2011 at 2:05 PM

I haven't quite understood where should I put this code. Would it be Application_Start (in case of ASP.NET MVC application, for example)?

Nov 11, 2011 at 10:28 PM

Yes, you are correct -- the code needs to run at startup in order to set up the container (which only needs to be done once).

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

Nov 15, 2011 at 7:52 AM

Ok, this method works, but it makes me stick to one connection string per one custom database class. Is there a way to use RetrySqlDatabase and be able to connect to different databases?

Nov 15, 2011 at 11:05 PM

There are (at least!) two ways to do what you want.  

You could just register multiple databases:

var injectionConstructor = new InjectionConstructor(
    new object[] 
            { 
                ConfigurationManager.ConnectionStrings["RetrySqlConnectionString1"].ConnectionString,
                System.Data.SqlClient.SqlClientFactory.Instance
            }
    );

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

injectionConstructor = new InjectionConstructor(
    new object[] 
            { 
                ConfigurationManager.ConnectionStrings["RetrySqlConnectionString2"].ConnectionString,
                System.Data.SqlClient.SqlClientFactory.Instance
            }
    );

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

var db1 = EnterpriseLibraryContainer.Current.GetInstance<Database>("RetrySqlDatabase1");
var db2 = EnterpriseLibraryContainer.Current.GetInstance<Database>("RetrySqlDatabase2");

Or you, if you maintain a reference to the container, you can use ResolverOverride to inject the values you want when you create the instance:

container.RegisterType<Database, RetrySqlDatabase>("RetrySqlDatabase");

var db = container.Resolve<Database>("RetrySqlDatabase", 
        new ParameterOverride[] 
        { 
            new ParameterOverride("connectionString", "MYCONN"),
            new ParameterOverride("dbProviderFactory", System.Data.SqlClient.SqlClientFactory.Instance)
        }
    );

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

Nov 16, 2011 at 10:34 AM

OK, this seems acceptable. Thank you.