0

Please can anyone advise if it is possible to switch connection strings for a DbContext using Ninject binding, based upon Current Culture? My current (non-working) cod is as below.

    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

    private static string GetCultureBasedConnectionString()
    {
        string culture = "de-DE"; // TODO Replce with Thread.CurrentThread.CurrentCulture.Name
        string cultureBasedConnectionString = ConnectionStringHelper.GetConnectionStringWithCulture(culture);
        return cultureBasedConnectionString;
    }

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<ApplicationDb>().To<ApplicationDb>()
            .InRequestScope()
            .WithConstructorArgument("connectionString", context => GetCultureBasedConnectionString());
        .
        .
        .
    }

This is based upon the example here, Ninject - dynamically specifying a connection string based on a sub domain, but it does not call through to my GetCultureBasedConnectionString() method on each request except when the application starts up...

I have read here on So that using NInjects Rebind() method is not good.

This SO thread also did not get me in the right direction, either.

Community
  • 1
  • 1
Dib
  • 2,001
  • 2
  • 29
  • 45

2 Answers2

1

Yes you are describing the expected behavior. The binding code is executed when.. well when you call Bind - and not every time the type is retrieved. The Func/Method specified in ToMethod would be executed every time the binding is applied.

Although i believe you can simplify your code to:

kernel.Bind<ApplicationDb>().To<ApplicationDb>()
        .InRequestScope()
        .WithConstructorArgument(
            "connectionStringGetter",
            context => GetCultureBasedConnectionString());

and thus get rid of ConnectionStringGetter().

BatteryBackupUnit
  • 12,934
  • 1
  • 42
  • 68
0

A slight change to use a Func<string> which calls back to my GetCultureBasedConnectionString() method and this seems to defer execution of the GetCultureBasedConnectionString() method until the HttpRequest is made, which now appears to be working for me... Is that anticipated behviour?

    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

    private static string GetCultureBasedConnectionString()
    {
        string culture = Thread.CurrentThread.CurrentCulture.Name;
        string cultureBasedConnectionString = ConnectionStringHelper.GetConnectionStringWithCulture(culture);
        return cultureBasedConnectionString;
    }

    private static Func<string> ConnectionStringGetter()
    {
        var function = new Func<string>(GetCultureBasedConnectionString); 
        return function;
    }

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<ApplicationDb>().To<ApplicationDb>()
            .InRequestScope()
            .WithConstructorArgument("connectionStringGetter", context => ConnectionStringGetter());
Dib
  • 2,001
  • 2
  • 29
  • 45