簡體   English   中英

多次通話'DbContext已被處理錯誤'

[英]'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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM