views:

196

answers:

2

I want to map DbConnection to an un-opened SqlConnection using Ninject. This is what I've done:

string constr = @"Server=.\SQLEXPRESS; Trusted_Connection=True; Database=TestDB";

Bind<DbConnection>().To<SqlConnection>()
    .Using<OnePerRequestBehavior>()
    .WithConstructorArgument("connectionString", constr);

However, when trying to use the db I get an error saying that

This operation requires a connection to the 'master' database. Unable to create a connection to the 'master' database because the original database connection has been opened and credentials have been removed from the connection string. Supply an unopened connection.

(The same operation works if I just provide the connection with new SqlConnection(constr)...)

It turns out the QueryString property of the SqlConnection I was given by Ninject is empty. What am I doing wrong?


UPDATE

I have now tested with kernel.Get<DbConnection>() directly after the binding, and with the above code it still gives me an empty connection string. The following works, although it is more verbose than I want it:

Bind<DbConnection>().ToMethod<SqlConnection>(ctx => GetConnection());

private SqlConnection GetConnection()
{ return new SqlConnection(constr); }

UPDATE 2

This is my entire module:

public class MsSqlModule : StandardModule
{
    private string constr = @"Server=AASLOEG\SQLEXPRESS; Trusted_Connection=True; Database=Booking_Test";// System.Configuration.ConfigurationManager.ConnectionStrings["mssql"].ConnectionString;

    public override void Load()
    {
        Bind<DbConnection>().To<SqlConnection>().WithConstructorArgument("connectionString", constr);
        var test = Kernel.Get<DbConnection>();
        test.Dispose();
    }
}

With a breakpoint on var test = Kernel.Get<DbConnection>(); and stepping over, I see that test is populated with an SqlConnection, but the ConnectionString property is empty.

A: 

The code you have seems fine, and Ninject should either use the binding or comnplain loudly iff you ask for a DBConnection.

Are you sure that ImplicitSelfBinding isnt stepping in ? Can you turn it off in yout Module? (But you'd need to be injecting a SqlConnection for that to happen).

What happens if you do a Get<DBConnection>() immediately after your Bind line?

Ruben Bartelink
I've updated my question with the results. How do I control ImplicitSelfBinding? (But no, I'm injecting `DbConnection`...)
Tomas Lycken
ImplicitSelfBindingDefault is passed into the Module (or is it Kernel or both?) construction. You can see what the state is by looking at the ImplicitSelfBinding prop of a Module. It only means that class X gets bound to X. (i.e., it probably has nothing to do with your case - if it was on and you had no Bindings then Ninject would allow you to Get a SqlConnection and it would be default constructed. If you're definitely resolving a DBConnection, it's not going to jump in and supply a default-constructed SqlConnection behind your back or anything crazy)
Ruben Bartelink
A: 

I ended up solving this by creating a custom provider, and binding to it. (I've also upgraded to Ninject 2.0, which might affect the results...)

public class MsSqlConnectionProvider : DbConnectionProvider<SqlConnection>
{
    public string ConnectionString { get { return TestConnectionString; } }
    public string ConnectionStringFromConfigFile { get { return System.Configuration.ConfigurationManager.ConnectionStrings["mssql"].ConnectionString; } }
    public string TestConnectionString { get { return @"Server=AASLOEG\SQLEXPRESS; Trusted_Connection=True; Database=Booking_Test"; } }

    protected override SqlConnection CreateInstance(IContext context)
    {
        return new SqlConnection(ConnectionString);
    }
}

public class MsSqlModule : NinjectModule
{
    public override void Load()
    {
        Bind<DbConnection>().ToProvider<MsSqlConnectionProvider>();
    }
}
Tomas Lycken

related questions