0
votes

Adding Structuremap MVC 5 to an ASP.NET MVC project. I would like to have a singleton of my database connection per request - my controllers would share the same database connection. I am implementing the repository pattern here and need each controller to have a copy of its respective repository. I know this is possible but I think I'm missing or mis-interpretting something wrong.

I have a controller, "Bag," that needs a "IBagRepo"

public class BagController : Controller
{
    private readonly IBagRepo repo;

    public BagController(IBagRepo repo)
    {
        this.repo = repo;
    }

    // actions
}

My first attempt was hooking the singleton database connection in the ControllerConvention, as I assume its called once

public class ControllerConvention : IRegistrationConvention {

    public void Process(Type type, Registry registry) {
        if (type.CanBeCastTo<Controller>() && !type.IsAbstract) {

            // Tried something like
            registry.For(type).Singleton().Is(new ApplicationDbContext()); // this
            registry.For(type).LifecycleIs(new UniquePerRequestLifecycle());
        }
    }
}

But it came clear that this isn't the right file to make this change. I went into the registry class that was automatically generated upon installing the nuget package and tried fiddling around with this.

    public class DefaultRegistry : Registry {
    #region Constructors and Destructors

    public DefaultRegistry() {
        Scan(
            scan => {
                scan.TheCallingAssembly();
                scan.WithDefaultConventions();
                scan.With(new ControllerConvention());
            });
        // httpContext is null if I use the line below
        // For<IBagRepo>().Use<BagRepo>().Ctor<ApplicationDbContext>().Is(new ApplicationDbContext());
    }

    #endregion
}

I haven't seen a problem like this out here yet. Am I passing in the right types within my DefaultRegistry class?

2

2 Answers

1
votes

What you're wanting is effectively the default behavior if you had been using the StructureMap.MVC5 nuget: https://www.nuget.org/packages/StructureMap.MVC5/. As long as your DbContext is registered with the default lifecycle, that package is using a nested container per http request which effectively scopes a DbContext to an HTTP request for unit of work scoping.

Different tooling than MVC & EF, but I described similar mechanics for FubuMVC + RavenDb w/ StructureMap in this blog post: http://jeremydmiller.com/2014/11/03/transaction-scoping-in-fubumvc-with-ravendb-and-structuremap/

0
votes

I ended overriding the default controller factory and not using structuremap