我正在 asp.net core 3.1 中的一个网站上工作,我试图在页面模型中读取数据库两次。但是,我收到“System.OnbjectDisposeException:无法访问已处置的对象”错误。这是我的 Index.cshtml.cs 的片段
public class IndexModel : PageModel
{
private readonly DocsiteContext _context;
public IndexModel(DocsiteContext context)
{
_context = context;
}
public Document CurrDocument;
public void OnGet()
{
FunctionA();
}
private async void FunctionA()
{
List<string> AllDocs = await _context.Documents.OrderBy(d => d.FileName).Select(d => d.FileName).ToListAsync();
FunctionB();
}
private async void FunctionB()
{
CurrDocument = await _context.Documents.FirstOrDefaultAsync(f => f.FileName == CurrPath && !f.IsDirectory);
}
}`
这是 Startup.cs 类的片段
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddDbContext<DocsiteContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DocsiteContext")));
}
我知道上下文在第一次使用后会被丢弃,但我不确定如何保留它以供第二次使用。 我对 ASP.NET 还很陌生,所以如果这是错误的方法,我希望得到一些建议!
DbContext 是一个“作用域”服务。这意味着为每个 HTTP 请求创建一个新的 dbContext。如果您执行重定向到另一个页面之类的操作,您将获得一个新的 dbContext 对象。
这里的问题是使用
async void
。
“即发即忘”任务不能保证运行完成: dotnet 运行时 和 IIS 都不知道
FunctionA();
是否完成了其工作。
OnGet()
将立即返回,导致请求的生命周期结束。
此时 ASP 中的任何 PageModel(或 MVC 中的控制器)都被卸载/处置。这样,注入的
DbContext
将有资格进行垃圾回收,并且 GC 很可能会在代码到达 FunctionB();
之前运行。
正如 Scott 在评论中提到的:使用
async Task
代替。