[英]'DbContext has been disposed error' on Multiple Calls
我已经设置了一个具有简单getCustomers()
方法的API。 端点在第一次调用时返回数据,但在第二次调用时返回错误。
错误:无法完成操作,因为DbContext已被释放
在return db.Customers...
上的CustomerService
导致错误return db.Customers...
问题:为什么这在第一次呼叫时起作用,但在第二次呼叫时失败。 怎么解决这个问题?
GitHub Repo可以在这里找到: https : //github.com/ChaseHardin/MyBookStore
这是代码的演练:
控制器:
[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();
}
}
}
BaseService
public class BaseService
{
public BaseService()
{
AutoMapperConfiguration();
}
public void AutoMapperConfiguration()
{
Assembly.GetExecutingAssembly()
.GetTypes()
.Where(x => x.IsClass && x.Namespace == "MyBookStore.Business.ViewModels")
.ForEach(x => System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(x.TypeHandle));
AutoMapper.Mapper.CreateMap<bool, short?>().ConvertUsing(x => x ? (short)1 : (short)0);
AutoMapper.Mapper.CreateMap<short, bool>().ConvertUsing(x => x == 1);
AutoMapper.Mapper.CreateMap<bool, int?>().ConvertUsing(x => x ? 1 : 0);
AutoMapper.Mapper.CreateMap<int?, bool>().ConvertUsing(x => x.HasValue && x.Value == 1);
AutoMapper.Mapper.CreateMap<short, int>().ConvertUsing(x => (int)x);
AutoMapper.Mapper.CreateMap<int, int?>().ConvertUsing(x => x);
}
}
CustomerViewModel
public class CustomerViewModel
{
static CustomerViewModel()
{
AutoMapper.Mapper.CreateMap<Customer, CustomerViewModel>().ReverseMap();
}
public Guid CustomerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
上下文设置:
public class Application
{
private static readonly MyBookStoreEntity Context = new MyBookStoreEntity();
public static MyBookStoreEntity GetDatabaseInstance()
{
return Context;
}
}
使用using
块时:
using (var db = Application.GetDatabaseInstance())
被“使用”的对象将被放置在块的末尾。 ( using
基本上是try/finally
语法简写,其中finally
块在对象上调用.Dispose()
。)
你正在“使用”的是这个价值:
private static readonly MyBookStoreEntity Context = new MyBookStoreEntity();
这个值是static
,所以每次调用时它都是MyBookStoreEntity
的相同实例。 但是当你第一次打电话给你时,你.Dispose()
它。 因此,任何后续调用都将在已处置的对象上。
基本上,您已经发现了static
数据库上下文非常糟糕的原因之一。 您仍然可以将数据库上下文封装到您拥有的方法中,但每次都使该方法返回一个新实例:
public static MyBookStoreEntity GetDatabaseInstance()
{
return new MyBookStoreEntity();
}
或者,如果此方法实际上没有提供任何好处,那么只需创建您需要它的上下文:
using (var db = new MyBookStoreEntity())
创建数据库上下文并不是特别繁重的操作。 但是当你不使用它们时保持它们是。 (并在不同的操作之间共享它们充满了危险。)一个好的经验法则是离散地定义您需要为给定的应用程序操作执行的数据库操作,并以紧密的代码创建/使用/配置您的数据库连接尽可能阻止这些操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.