为什么WebApi控制器操作后没有人处理DbContext?
我知道各种教程以及针对具有WebApi
控制器的WebApi
和Entity Framework
(甚至来自Microsoft)的完整示例,如下所示:
public HttpResponseMessage GetInternet(int id) { var context = new InternetDbContext(); var result = (from internet in context.Internets where internet.Id.Equals(id) select internet).FirstOrDefault(); if(result != null) Request.CreateResponse(HttpStatusCode.OK, result); }
但是,当我在2年前学习Entity Framework
,我发现的关于框架的每一个资源都指出了在最短的可能生命周期中 DbContex
是多么重要,例如使用’ using
‘。 而现在,人们似乎并没有放弃处理任何东西(他们的经理,存储库,DI容器……)。
我在这里错过了什么吗? API调用的结尾是否会自动处理上下文? 或者我必须使用来自http://msdn.microsoft.com/en-us/library/dn153859(v=vs.118).aspx的 HttpRequestMessageExtensions.RegisterForDispose()
类的东西?
就个人而言,每当我看到类型实现IDisposable
,我几乎可以肯定在处理这种类型的新实例时我将使用using
语句。
当变量超出范围时(例如,当执行从GetInternet
方法返回时, context
变量超出范围),其内存最终将由垃圾收集器回收,但这并不意味着任何本机处理程序(例如文件处理程序或数据库连接)将被关闭,这会对您的应用程序产生非常严重的负面影响。
因此,请考虑始终将IDisposable
包装到using
构造中:
using (var context = new InternetDbContext()) { // Your code goes here }
希望这可以帮助。
有时处理上下文是个坏主意 。 例如,我有一个像这样的WebAPI2控制器方法,
[Route("Questionnaires")] public IEnumerable GetAllQuestionnaires() { NMQContext context = new NMQContext(); return context.Questionnaires.AsEnumerable(); }
结果数据是JSON列表,调查表是一个复合对象 – 它包含来自多个数据库表的实体。 如果我用“使用”包装它,我会收到错误,例如
"Message": "An error has occurred.", "ExceptionMessage": "The operation cannot be completed because the DbContext has been disposed.",
如果您尝试序列化复合对象,那么最好不要处置连接。 最好让EF为你处理它。 您可以通过明确的急切加载来修复它,但这很痛苦。 不要这样做。
使用的主要情况,无论退出方法如何,您的DbContext都将被处理;
public HttpResponseMessage GetInternet(int id) { using(var context = new InternetDbContext()) { var result = (from internet in context.Internets where internet.Id.Equals(id) select internet).FirstOrDefault(); if(result != null) Request.CreateResponse(HttpStatusCode.OK, result); } }
你应该使用上下文类的Dispose()
,所以使用using
构造:
using (var context = new InternetDbContext()) { // your code here, try/catch is auto-generated by the compiler }
这是因为他们错了。 不要相信别人的代码,特别是当它是在线教程的一部分时。
你应该在实例化DbContext
之后调用Dispose()
,或者使用但不必using
。
长话短说,EF知道什么时候打开和关闭一个连接,所以在大多数情况下调用或不调用Dispose()
会产生相同的结果而不会对内存或性能产生任何影响,这与大多数IDisposable情况不同。
但是 ,有两个主要原因你应该调用Dispose()
。
首先,如果有人强行打开与DbContext
ObjectContext
连接,如果你不调用Dispose()
你可以保持打开连接。
第二个但并非最不重要的是,您实例化的DbContext
的派生类可能会过度处理dispose的默认行为,例如将其他非托管资源聚合到上下文的生命周期中。
这篇文章是必读的。
你应该使用magic关键字“使用”。 它会自动处理。
using (var context = new DBContext()) { //code here }