前言
使用了ASP.NET MVC Framework Entity AutoFac 的 项目,最近发现不同的HTTP请求Controller-Action 的时候,出现了错误,The context cannot be used while the model is being created , 大概的意思就是出现了线程共享安全的问题,在entity 返回IQueryable 转化成ToList 对象的时候抛出这个错误。
起初以为是使用了entity 数据库关系对象,主键和外键引用出现了问题,经过反复测试,发现不是这个问题,然后又考虑是不是使用了IOC单个例程SingleInstance() 的问题, 然后修改成生命周期注入InstancePerLifetimeScope(), 还是不能解决问题。最后仔细观察发现,原来是BLL和接口使用了IOC注入,DAL也使用了IOC注入, 但是 Entity 基类接口和 DAL数据库访问接口使用了静态单个例程的上下文,当然是用这种方式是正确的,但是恰好这里就出现了单例程共享访问冲突。
正常情况:一个HTTP请求访问在后台处理过程如下:
Client(浏览器)->HTTPRequest -> MVCController (IOC注入BLL)-> BLL (IOC注入DAL)->DAL(访问Entity基类)
看出来问题了吧? Entity 建议对于单个用户建议使用相同的上下文例程,但是不同的HTTP请求不同又用户不能共享例程。
解决方案:
上面是通过静态对象共享一个上下文的方式,这种方式不能通过IOC注入。
如上图,修改为通过 注入DbContextFactory 类和接口的方式IOC注入。
BLL和DAL的注入依旧使用单例程。
然后在BaseDal Entity 基类中对 DbContext 对象进行注入。
完整的项目结构如上图, 最终数据绑定的页面:这个页面有两个Ajax 请求 Action返回数据,不会报异常。