IoC和dataContext在asp.net mvc 2应用程序中处理

时间:2010-06-01 21:51:24

标签: asp.net garbage-collection inversion-of-control

我有Global.asax,如下面的代码:

public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
    // ....
    }

    protected void Application_Start()
    {
    AreaRegistration.RegisterAllAreas();

    RegisterRoutes(RouteTable.Routes);

    ControllerBuilder.Current.SetControllerFactory(typeof(IOCControllerFactory));
    }
}

public class IOCControllerFactory : DefaultControllerFactory
{
    private readonly IKernel kernel;

    public IOCControllerFactory()
    {
        kernel = new StandardKernel(new NanocrmContainer());
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
            return base.GetControllerInstance(requestContext, controllerType);

        var controller = kernel.TryGet(controllerType) as IController;

        if (controller == null)
            return base.GetControllerInstance(requestContext, controllerType);

        var standartController = controller as Controller;

        if (standartController is IIoCController)
            ((IIoCController)standartController).SetIoc(kernel);

        return standartController;
    }

    class NanocrmContainer : Ninject.Modules.NinjectModule
    {
        public override void Load()
        {
            // ...

            Bind<DomainModel.Entities.db>().ToSelf().InRequestScope().WithConstructorArgument("connection", "Data Source=lims;Initial Catalog=nanocrm;Persist Security Info=True;User ID=***;Password=***");
        }
    }
}

在这种情况下,如果某个地方是类,则定义如下:

public class UserRepository : IUserRepository
{
    private db dataContext;
    private IUserGroupRepository userGroupRepository;

    public UserRepository(db dataContext, IUserGroupRepository userGroupRepository)
    {
        this.dataContext = dataContext;
        this.userGroupRepository = userGroupRepository;
    }
}

然后由Ninject创建dataContext实例(如果在此请求范围内没有创建任何人)。

现在麻烦的是 - 在哪里调用dataContext方法.Dispose()

UPD

所以我按照 KeeperOfTheSoul 的建议,以这种方式解决了问题:

    public override void ReleaseController(IController controller)
    {
        base.ReleaseController(controller);

        var db = kernel.Get<DomainModel.Entities.db>();
        db.Dispose();
    }

3 个答案:

答案 0 :(得分:3)

处理此问题的好地方是IControllerFactory.ReleaseController,例如

public override void ReleaseController() {
    base.ReleaseController();
    //Do whatever you need to clean up the IoC container here
}

在NInject中,这可以通过使用activation block进行范围处理,在创建控制器时,在创建控制器时可以将激活块存储在HttpContext的当前项中,在ReleaseController期间,您可以检索先前创建的激活阻止并处置它。

您还可以考虑使用InScope并让自定义范围实现INotifyWhenDisposed。之后,使用情况与激活块相同,但现在将范围存储在HttpContext的当前项中。

答案 1 :(得分:2)

有时用于处理数据库连接的模式是从终结者调用Dispose

public class db : IDisposable {
   //called by the garbage collector 
   ~db() {
     //Call dispose to make sure the resources are cleaned up
     Dispose(false);
   }

   //IDisposable implementation
   public void Dispose() {
     Dispose(true);
   }
   //subclasses of db can override Dispose(bool) and clean up their own fields
   protected virtual void Dispose (bool disposing) {
     if (disposing) {
       //Supress finalization as all resources are released by this method
       //Calling Dispose on IDisposable members should be done here
       GC.SupressFinalize();
     }
     //Clean up unmanaged resources
     //Do not call other objects as they might be already collected if called from the finalizer
   }
}

答案 2 :(得分:1)

您可以将其挂钩到Application_EndRequest。