Joshua Hayes
Joshua Hayes

Reputation: 1958

How to configure Ninject for ASP.NET MVC using LinqToSQL and Repository Pattern

I have done some searching around but have not been able to figure out how to bind LinqToSql data context's with specified connection strings into different repositories.

This binding is performed in global.ajax when routes are registered. I'm using a fairly standard repository pattern to decouple the LinqToSql infrastructure from my application so that I can change the technology infrastructure in the future (NHibernate, EntityFramework etc.). Additionally, make my code easily unit testable and mockable.

I have something like this.

string desktopConnectionString = ConfigurationManager.ConnectionStrings["Desktop"].ConnectionString;
string messagingConnectionString = ConfigurationManager.ConnectionStrings["MessageQueue"].ConnectionString;
string usersConnectionString = ConfigurationManager.ConnectionStrings["Users"].ConnectionString;

// Map linqToSql entity types to interfaces
TableMapper typeFinder = new TableMapper();
typeFinder.Define<EzsDashboard>().As<IDashboard>();
typeFinder.Define<EzsDashboardGadget>().As<IGadget>();
typeFinder.Define<EzsDashboardGadgetAssignment>().As<IGadgetAssignment>();
...

IDesktopRepository dr = new DesktopRepository(new LinqToSqlDataSource(new DataContext(desktopConnectionString), typeFinder)));
Bind<IDesktopRepository>().ToConstant(dr).InRequestScope();

IUserRepository ur = new UserRepository(new LinqToSqlDataSource(new DataContext(usersConnectionString), typeFinder)));
Bind<IUserRepository>().ToConstant(ur).InRequestScope();

IMessageRepository mr = new MessageRepository(new LinqToSqlDataSource(new DataContext(messagingConnectionString), typeFinder)));
Bind<IMessageRepository>().ToConstant(mr).InRequestScope();

Whilst this physically works. I find the data in my asp.net MVC app often comes back stale. For example, I'll add a gadget to the dashboard it displays and if I check the database, it was saved correctly into the database. I reload the page and the dashboard doesn't show anything. Clicking around the application will sometimes cause it to 'refresh' and the data that was saved shows up.

Another way this is visible is if I make a changed to my web.config and trigger an application re-load. When I hit the dashboard everything shows up exactly as it should.

Can somebody please provide some help with binding connection string->DataContext->LinqToSqlDataSource->DomainRepository

Upvotes: 1

Views: 907

Answers (2)

John Bledsoe
John Bledsoe

Reputation: 17692

It looks to me like your repositories are outlasting the scope that you expect. Am I correct to assume that the code in your question is in a Ninject module or global application start up? If so, I would change each of your bindings to something like this:

Bind<IDesktopRepository>().ToMethod(context => new DesktopRepository(new LinqToSqlDataSource(new DataContext(desktopConnectionString), typeFinder)))).InRequestScope();

I believe that you're getting the same repository across requests, because you've bound it to a constant. I would want a new repository per request, which the above code will provide.

Upvotes: 1

Ruben Bartelink
Ruben Bartelink

Reputation: 61893

I typed this but, on reflection, I have no idea what you are asking... Can you clarify:

  • at a high level, what do these connection strings achieve in your app
  • what you feel is going wrong in your system?
  • do you feel this is an ASP.NET issue or a DI issue? Are you cahcing stuff in a session etc.?

You need to surface stuff like this (assuming I've inferred correctly that you want to dynamically be able to change your application's storage mechanism on the fly - you've stated what you are doing, not why you are doing it) as application logic.

Trying to abuse a DI container to do this for you is bad news - it doesnt retain a tree of objects it give the old configuration to, etc. Your application needs to manage this.

Think of the case where you switch storage from A to B. What if something in your app is contacting A in the middle of your operation and is about to retry? You dont want the container (or anyone else) handing it a B instead.

That's not to say that there are no legitimate use cases for such things. It's just that they're definitely not a common case or something that DI containers are typically used to manage.

... Or I may be missing something - in which case, it'd be interesting to hear more about your scheme and how you are attempting to map things to scopes etc.

Upvotes: 0

Related Questions