C# ';DbContext已被释放错误';多次通话
我已经设置了一个API,它有一个简单的C# ';DbContext已被释放错误';多次通话,c#,entity-framework,automapper,C#,Entity Framework,Automapper,我已经设置了一个API,它有一个简单的getCustomers()方法。端点在第一次调用时返回数据,但在第二次调用时返回错误 错误:操作无法完成,因为DbContext已被释放 该错误是由myCustomerService中的返回数据库引起的。Customers… 问题:为什么这在第一次通话中有效,但在第二次通话中失败。如何解决这个问题 GitHub回购协议可在此处找到: 下面是代码的演练: [RoutePrefix("api/customers")] public class Customer
getCustomers()
方法。端点在第一次调用时返回数据,但在第二次调用时返回错误
错误:操作无法完成,因为DbContext已被释放
该错误是由myCustomerService
中的返回数据库引起的。Customers…
问题:为什么这在第一次通话中有效,但在第二次通话中失败。如何解决这个问题
GitHub回购协议可在此处找到:
下面是代码的演练:
[RoutePrefix("api/customers")]
public class CustomerController : ApiController
{
private readonly CustomerService _service = new CustomerService();
[HttpGet, Route("")]
public virtual IHttpActionResult Get()
{
var customers = _service.GetCustomers();
return Ok(new {customers});
}
}
public class CustomerService : BaseService
{
public List<CustomerViewModel> GetCustomers()
{
using (var db = Application.GetDatabaseInstance())
{
return db.Customers.Select(AutoMapper.Mapper.Map<CustomerViewModel>).ToList();
}
}
}
public class Application
{
private static readonly MyBookStoreEntity Context = new MyBookStoreEntity();
public static MyBookStoreEntity GetDatabaseInstance()
{
return Context;
}
}
控制器:
[RoutePrefix("api/customers")]
public class CustomerController : ApiController
{
private readonly CustomerService _service = new CustomerService();
[HttpGet, Route("")]
public virtual IHttpActionResult Get()
{
var customers = _service.GetCustomers();
return Ok(new {customers});
}
}
public class CustomerService : BaseService
{
public List<CustomerViewModel> GetCustomers()
{
using (var db = Application.GetDatabaseInstance())
{
return db.Customers.Select(AutoMapper.Mapper.Map<CustomerViewModel>).ToList();
}
}
}
public class Application
{
private static readonly MyBookStoreEntity Context = new MyBookStoreEntity();
public static MyBookStoreEntity GetDatabaseInstance()
{
return Context;
}
}
客户服务:
[RoutePrefix("api/customers")]
public class CustomerController : ApiController
{
private readonly CustomerService _service = new CustomerService();
[HttpGet, Route("")]
public virtual IHttpActionResult Get()
{
var customers = _service.GetCustomers();
return Ok(new {customers});
}
}
public class CustomerService : BaseService
{
public List<CustomerViewModel> GetCustomers()
{
using (var db = Application.GetDatabaseInstance())
{
return db.Customers.Select(AutoMapper.Mapper.Map<CustomerViewModel>).ToList();
}
}
}
public class Application
{
private static readonly MyBookStoreEntity Context = new MyBookStoreEntity();
public static MyBookStoreEntity GetDatabaseInstance()
{
return Context;
}
}
当您使用
块时:
using (var db = Application.GetDatabaseInstance())
正在“使用”的对象将被放置在块的末尾。(using
基本上是try/finally
的语法简写,其中finally
块调用对象上的.Dispose()
你“使用”的是这个值:
private static readonly MyBookStoreEntity Context = new MyBookStoreEntity();
该值是静态的,因此每次调用时都是MyBookStoreEntity的同一个实例。但是当您第一次调用它时,您将.Dispose()
它。因此,任何后续调用都将针对已处置的对象
基本上,您已经发现了静态
数据库上下文是一个非常糟糕的主意的原因之一。您仍然可以像以前一样将数据库上下文封装到方法中,但每次都要使该方法返回一个新实例:
public static MyBookStoreEntity GetDatabaseInstance()
{
return new MyBookStoreEntity();
}
或者,如果该方法在这一点上没有真正提供任何好处,那么只需在需要的地方创建上下文:
using (var db = new MyBookStoreEntity())
创建数据库上下文并不是一项特别繁重的操作。但是当你不使用它们的时候,把它们放在身边是很困难的。(在不同的操作之间共享它们充满了危险。)一个好的经验法则是离散地定义您需要为给定的应用程序操作执行的数据库操作,以及在这些操作周围尽可能紧密的代码块中创建/使用/处置数据库连接。看起来您的上下文是一个单例,您在使用它之后正在处置它。您在using语句中使用静态上下文,所以请使用它一次,然后将其处置。永远不要使用静态上下文!静态数据库上下文是一个众所周知的坏主意。您已经发现了其中一个原因。好的,所以我删除了静态数据库上下文并实例化了我的应用程序。但是,我仍然会遇到DbContext错误。还有其他想法吗?现在展示代码的外观。