收录日期:2019/12/09 08:24:14 时间:2010-10-28 14:08:55 标签:asp.net-mvc,entity-framework

I would like to use the Session-per-request pattern, as is done frequently when using NHibernate in an ASP.NET environment.

My first thought was to put the code to create the context in the BeginRequest event handler in Global.asax, but I discovered that this event is firing not only for the initial request that actually does the work, but also for the subsequent requests for static files such as CSS and images.

I don't want to create a whole bunch of extra contexts when they're not needed, so is there a way I can just get my code to run on the initial request, and not the ones for the static files?

  1. Use constructor injection for anything which needs a context.
  2. Use the DI framework of your choice and map the context.
  3. Scope the context as request-scoped.

When I'm using a dependency injection framework I typically have a separate assembly with the domain model in it. That assembly also contains interfaces for repositories. The implementation of the repository contains the code that actually instantiates the EF ObjectContext.

If this is a really simple application though and you're not doing DI you could always instantiate the EF ObjectContext within the constructor of your controller. Have a look at the ASP.NET MVC sample applications at http://www.asp.net/mvc for good basic information on getting started. I think all three of the sample applications they have use EF now.

Are you using IIS 6 with wildcard mapping? CSS and Images shouldn't trigger BeginRequest.

Another popular way to do this is by overriding the OnActionExecuted and OnActionExecuting methods inside of a base Controller.

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        _context = new SomeEntities();
        base.OnActionExecuting(filterContext);
    }

    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        _context.Dispose();
        base.OnActionExecuted(filterContext);
    }

If you are running in IIS 7 with an integrated pipeline (the default), your ASP.NET module will see every request, even the requests for static content (see http://learn.iis.net/page.aspx/508/wildcard-script-mapping-and-iis-7-integrated-pipeline/),

If you still want to use an HTTP module to manage a session/content per request, I'd consider using Lazy to avoid instantiating the context when it is not needed.

If you use an action filter, you'll need to finish all the work early if you dispose the context during OnActionExecuted. Wait and dispose during OnResultExecuted if you want to defer query execution until the view renders, or use deferred / lazy loading of entities.

As Craig pointed out, the IoC containers can also manage the lifetime for you.