为什么WebApi控制器操作后没有人处理DbContext?

我知道各种教程以及针对具有WebApi控制器的WebApiEntity 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 }