带有 EF Core 的 .NET 项目在一个特定页面上引发 ObjectDisposedException

Posted

技术标签:

【中文标题】带有 EF Core 的 .NET 项目在一个特定页面上引发 ObjectDisposedException【英文标题】:.NET project with EF Core throws ObjectDisposedException on one particular page 【发布时间】:2022-01-07 12:10:13 【问题描述】:

当我尝试访问页面时,带有 Entity Framework 的 ASP.NET Core 项目出错。我尝试用谷歌搜索错误,我的方法是使用async Task 而不是 void,我在AddDbContextPool 上设置了sqlOptions.EnableRetryOnFailure();。但是当我们访问该页面时,它仍然会出错

ObjectDisposedException:无法访问已释放的上下文实例。此错误的一个常见原因是释放从依赖注入中解析的上下文实例,然后尝试在应用程序的其他地方使用相同的上下文实例。如果您在上下文实例上调用“Dispose”或将其包装在 using 语句中,则可能会发生这种情况。如果你使用依赖注入,你应该让依赖注入容器负责处理上下文实例。

在我正在缓存的页面的Index()

 public class CustomersController : Controller
 
     private readonly SurplusMouseContext _context;
     private readonly IMemoryCache memoryCache;

     public CustomersController(SurplusMouseContext context, IMemoryCache _memoryCache)
     
         _context = context;
         memoryCache = _memoryCache;
      

     // GET: Customers
     public async Task<IActionResult> Index(string sortOrder, string searchString,
                                            int? pageNumber, string currentFilter)
     
         var timeUtc = DateTime.UtcNow;

         IQueryable<JAXSurplusMouseApp.Models.Setting> settings_data = null;
         IQueryable<JAXSurplusMouseApp.Models.HolidayWeek> holidaycheck = null;

         TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
         var todayDt = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, easternZone);

         TimeSpan timeNow = TimeSpan.Parse(todayDt.ToString("HH:mm:ss"));

         bool isExist = memoryCache.TryGetValue("HolidayWk", out holidaycheck);

         if (!isExist)
         
             holidaycheck = (from hc in _context.HolidayWeeks
                             where hc.HolidateDate == todayDt.Date
                             select hc);
             var cacheEntryOptions = new MemoryCacheEntryOptions()
                .SetSlidingExpiration(TimeSpan.FromHours(2));

             memoryCache.Set("HolidayWk", holidaycheck, cacheEntryOptions);
         

         bool isSettingExist = memoryCache.TryGetValue("SMSettings", out settings_data);

         if (!isSettingExist)
         
            settings_data = (from s in _context.Settings                                
                             select s).Take(1);
            var cacheEntryOptions = new MemoryCacheEntryOptions()
                     .SetSlidingExpiration(TimeSpan.FromHours(2));

            memoryCache.Set("SMSettings", settings_data, cacheEntryOptions);
         

         int i = settings_data.Count();

         if (holidaycheck.Count() != 0)
         
             HolidayWeek viewmodel = new HolidayWeek
                         
                             Holiday = holidaycheck.First().Holiday.ToUpper()
                         ;

             return View("/Views/Customers/AppNotAvailableHoliday.cshtml", viewmodel);
         
         else if (settings_data.Count() != 0)
         
             string myCondition = (todayDt.DayOfWeek.ToString().Substring(0, 3)).ToUpper();
             string abc = settings_data.First().OrderDay;

             TimeSpan start = TimeSpan.Parse(settings_data.First().StartTime);
             TimeSpan end = TimeSpan.Parse(settings_data.First().EndTime);

             bool checktime = (timeNow >= start) && (timeNow <= end);

             if ((settings_data.First().OrderDay == myCondition)&&((timeNow>=start) && (timeNow <= end)))
             
                 ViewData["CustomerParam"] = String.IsNullOrEmpty(sortOrder) ? "customer_desc" : "";
                ViewData["LocationParam"] = String.IsNullOrEmpty(sortOrder) || sortOrder == "location_asc" ? "location_desc" : "location_asc";

                ViewData["CurrentFilter"] = searchString;
                ViewData["CurrentSort"] = sortOrder;

                if (searchString != null)
                
                    pageNumber = 1;
                
                else
                
                    searchString = currentFilter;
                

                var cust = from s in _context.Customers
                           select s;

                if (!String.IsNullOrEmpty(searchString))
                
                    cust = cust.Where(s => s.Location.Contains(searchString));
                

                switch (sortOrder)
                
                    case "location_desc":
                        cust = cust.OrderByDescending(s => s.Location);
                        break;

                    case "location_asc":
                        cust = cust.OrderBy(s => s.Location);
                        break;

                    case "customer_desc":
                        cust = cust.OrderBy(s => s.CustomerNumber);
                        break;

                    default:
                        cust = cust.OrderBy(s => s.Location);
                        break;
                

                int pageSize = 15;

                return View(await PaginatedList<Customer>.CreateAsync(cust.AsNoTracking(), pageNumber ?? 1, pageSize));
           
           else
           
                Setting ss = new Setting
                
                    OrderDay = settings_data.First().OrderDay,
                    StartTime = settings_data.First().StartTime,
                    EndTime = settings_data.First().EndTime
                ;

                return View("/Views/Customers/AppNotAvailableSettings.cshtml", ss);
           
       

       return View("/Views/Customers/AppNotAvailableSettings.cshtml");           
    

我正在查询两个不同的表 HolidayWeekSetting 以检查客户页面是否可用。如果无法访问客户页面,我会向用户返回不同的视图。我不确定我是否缺少缓存部分的任何内容。

这个错误一出现就非常不一致,然后又失败了。任何人都可以建议我是否在这里遗漏了什么?

【问题讨论】:

【参考方案1】:

您正在尝试缓存IQueryable,这是查询的延迟执行。它包含对DbContext 的引用,稍后由容器处理。

所以解析很简单——在缓存之前实现对象:

memoryCache.Set("HolidayWk", await holidaycheck.ToListAsync(), cacheEntryOptions);

其他地方也有同样的错误。

无论如何,您可能必须更改缓存条目的类型:

public async Task<IActionResult> Index(string sortOrder, string searchString,
                                        int? pageNumber, string currentFilter)

    var timeUtc = DateTime.UtcNow;

    List<JAXSurplusMouseApp.Models.Setting> settings_data = null;
    List<JAXSurplusMouseApp.Models.HolidayWeek> holidaycheck = null;

    TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
    var todayDt = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, easternZone);

    TimeSpan timeNow = TimeSpan.Parse(todayDt.ToString("HH:mm:ss"));

    bool isExist = memoryCache.TryGetValue("HolidayWk", out holidaycheck);

    if (!isExist)
    
        holidaycheck = await (from hc in _context.HolidayWeeks
                        where hc.HolidateDate == todayDt.Date
                        select hc).ToListAsync();
        var cacheEntryOptions = new MemoryCacheEntryOptions()
        .SetSlidingExpiration(TimeSpan.FromHours(2));

        memoryCache.Set("HolidayWk", holidaycheck, cacheEntryOptions);
    

    bool isSettingExist = memoryCache.TryGetValue("SMSettings", out settings_data);

    if (!isSettingExist)
    
        settings_data = await (from s in _context.Settings                                
                            select s).Take(1).ToListAsync();
        var cacheEntryOptions = new MemoryCacheEntryOptions()
                    .SetSlidingExpiration(TimeSpan.FromHours(2));

        memoryCache.Set("SMSettings", settings_data, cacheEntryOptions);
    
  ...

【讨论】:

你能帮我解决我遇到的其他错误吗 settings_data 也缓存为IQueryable 但我无法更改 await holidaycheck.ToListAsync() 它会抛出错误 'IQueryable&lt;HolidayWeek&gt;' does not contain a definition for 'ToListAsync' and no accessible extension method 'ToListAsync' accepting a first argument of type 'IQueryable&lt;HolidayWeek&gt;' could be found (are you missing a using directive or an assembly reference?) 怎么可能?这是广泛使用的 EF Core 扩展。可能你必须添加using Microsoft.EntityFrameworkCore; 我已经有了using Microsoft.EntityFrameworkCore; 我可以保留IQueryable&lt;JAXSurplusMouseApp.Models.HolidayWeek&gt; holidaycheck = null; 原样吗?

以上是关于带有 EF Core 的 .NET 项目在一个特定页面上引发 ObjectDisposedException的主要内容,如果未能解决你的问题,请参考以下文章

带有 EF Core 的 ASP.NET Core - DTO 集合映射

带有 EF Core / ASP.NET Core 的 OData - 好还是坏?

带有 EF Core 和 CosmosDB .NET 5 的 ASP.Net Core - IdentityRole 问题

带有 UWP 的 EF Core - Visual Studio 19

带有 EF Core 更新实体的 ASP.Net 核心 Web Api 如何

如何在现有数据库 ASP.NET Core MVC 和 EF Core(DB-First)中使用 Identity