我想将dbContext的生命周期与会话的生命周期联系起来,例如 - 能够在多个请求上提交或放弃对dbcontext上的一组突变的更改。
还有其他(更好的?)方法来实现这一目标吗?如果不是,那么创建和处理上下文的合适机制是什么?我正在考虑在会话结束时使用清理的静态哈希表,但也许我正在做它所有错误。我也在考虑只关注那些必须在多个请求上工作的上下文,并保持其余的每个操作的想法。有什么建议吗?
答案 0 :(得分:6)
您可以使用 IoC(控制反转)容器来管理DBContext的生命周期,例如 StructureMap ,步骤如下:
为MVC 4安装nuget包: http://nuget.org/packages/StructureMap.MVC4
设置DBContext的范围: http://docs.structuremap.net/Scoping.htm
此外,您可以使用存储库和工作单元格的组合来提交或放弃对多个请求的dbcontext上的一组突变的更改。
答案 1 :(得分:4)
这个问题在以下SO帖子中得到了相当优雅的回答:
StructureMap CacheBy InstanceScope.HttpSession not working
基本上,魔术来自以下代码(适用于您的问题和StructureMap
的新语法):
ObjectFactory.Initialize(factory => {
factory.For<MyContext>()
.CacheBy(InstanceScope.HttpSession)
.Use(new MyContext(_myConnectionString));
});
然后 - 在您的控制器中,只需使用:
创建对象的实例var db = ObjectFactory.GetInstance<MyContext>();
因为您通过StructureMap
设置的IoC(控制反转)已将实例配置为范围为HttpSession
,所以只要会话相同,您就应该每次都检索相同的上下文
然而 - 请记住,对于DbContext
个对象,特别是这通常是一个非常糟糕的想法 - 因为您正在将状态跟踪对象与无状态环境混合,并且很容易让自己进入一个状态,在这种状态下,一个错误的事务或处于奇怪状态的对象可以阻止你进行任何进一步的数据库调用,直到你刷新你的会话。
DbContext
物品通常设计得非常轻便且一次性使用。完全可以让他们退出范围,并在你完成它们后立即死掉。
答案 2 :(得分:2)
让DbContext与会话一起使用并不是一件好事。
当您有更多请求时,它会将部分数据从数据库加载到上下文中,这会使上下文变得更大,这意味着内存问题,
在上下文中,每个请求与DbContet相比,您不会更新数据,因为另一个用户(另一个会话)可能已经更新了您已加载到上下文的数据。
Caching Entity Framework DbContexts per request
请阅读此选项,
答案 3 :(得分:1)
通常在这种情况下,您需要在临时存储中保留更改(如会话或cookie或数据库)。当您需要保存结果或查看新数据时,您将获得旧数据和更改并构建新对象。更改可以存储为新对象或操作序列。应用更改时可能会出现数据冲突,可能会发生数据冲突。资源使用Context \ Request
答案 4 :(得分:0)
理论上,您可以将上下文存储到您可以在每个控制器中访问的会话字典中。但是,您可能会遇到一些线程问题,因为在您存储它时,您所处的线程与检索它时不同。如果上下文不使用threadstatic变量,这可能会起作用(但我不确定),否则不行。在任何情况下,这都是糟糕的设计...网上都没有这样做...你为什么要存储上下文?您可以在后续的http请求中以便宜的价格重新创建它。如果您需要跟踪属性的变化,还有其他更适合网络的方法。