EF 核心 ToAsyncEnumerable 和 AsAsyncEnumerable 以 System.ObjectDisposedException 结尾
EF core ToAsyncEnumerable and AsAsyncEnumerable ends with System.ObjectDisposedException
我正在研究 xamarin 项目并使用 Entity Framework Core 访问数据库。我知道这不是一个好的解决方案,但我决定在没有应用程序服务器的情况下这样做。
DAL 层正在使用存储库模式,而 BL 层正在使用带有映射器的外观模式。
在 DAL 层上,我想创建实体的 IAsyncEnumerable,在 BL 上,我想创建模型的 IAsyncEnumerable。
第一个和第二个示例不起作用,它以 System.ObjectDisposedException“无法访问已处置的上下文实例...”结束,为什么? ToList() 运行良好,ToListAsync() 运行良好。
结束于 System.ObjectDisposedException
public IAsyncEnumerable<TaskEntity> GetTasksByTaskGroupIdAndKanbanStateAsync(Guid taskGroupId, string kanbanStateName, CancellationToken token)
{
using (WorkManagerDbContext dbContext = IdbContextFactory.CreateDbContext())
{
return dbContext.TaskSet.AsQueryable().Where(s => s.TaskGroup.Id == taskGroupId)
.Where(s => s.State.Name == kanbanStateName).ToAsyncEnumerable();
}
}
结束于 System.ObjectDisposedException
public IAsyncEnumerable<TaskEntity> GetTasksByTaskGroupIdAndKanbanStateAsync(Guid taskGroupId, string kanbanStateName, CancellationToken token)
{
using (WorkManagerDbContext dbContext = IdbContextFactory.CreateDbContext())
{
return dbContext.TaskSet.AsQueryable().Where(s => s.TaskGroup.Id == taskGroupId).
Where(s => s.State.Name == kanbanStateName).AsAsyncEnumerable();
}
}
有效 解决方案,但我不知道它是否是好的解决方案。
public IAsyncEnumerable<TaskEntity> GetTasksByTaskGroupIdAndKanbanStateAsync(Guid taskGroupId, string kanbanStateName, CancellationToken token)
{
using (WorkManagerDbContext dbContext = IdbContextFactory.CreateDbContext())
{
return dbContext.TaskSet.AsQueryable().Where(s => s.TaskGroup.Id == taskGroupId)
.Where(s => s.State.Name == kanbanStateName).ToList().ToAsyncEnumerable();
}
}
发生这种情况是因为 .ToAsyncEnumerable() 将在您使用对象(延迟加载)时执行数据库调用。 ToList() 将立即执行数据库调用。因此,当您在 using 语句中使用它时,DbContext 会在 return 对象被 returned 时被释放。 .ToList() 是这种情况下的正确解决方案。
但是,我对您创建和处理 DbContext 的方法表示怀疑,因为它可能会在以后导致其他问题(例如更新在另一个上下文实例中跟踪的对象等)。你也会失去一些好处,比如结果缓存。
我正在研究 xamarin 项目并使用 Entity Framework Core 访问数据库。我知道这不是一个好的解决方案,但我决定在没有应用程序服务器的情况下这样做。
DAL 层正在使用存储库模式,而 BL 层正在使用带有映射器的外观模式。 在 DAL 层上,我想创建实体的 IAsyncEnumerable,在 BL 上,我想创建模型的 IAsyncEnumerable。
第一个和第二个示例不起作用,它以 System.ObjectDisposedException“无法访问已处置的上下文实例...”结束,为什么? ToList() 运行良好,ToListAsync() 运行良好。
结束于 System.ObjectDisposedException
public IAsyncEnumerable<TaskEntity> GetTasksByTaskGroupIdAndKanbanStateAsync(Guid taskGroupId, string kanbanStateName, CancellationToken token)
{
using (WorkManagerDbContext dbContext = IdbContextFactory.CreateDbContext())
{
return dbContext.TaskSet.AsQueryable().Where(s => s.TaskGroup.Id == taskGroupId)
.Where(s => s.State.Name == kanbanStateName).ToAsyncEnumerable();
}
}
结束于 System.ObjectDisposedException
public IAsyncEnumerable<TaskEntity> GetTasksByTaskGroupIdAndKanbanStateAsync(Guid taskGroupId, string kanbanStateName, CancellationToken token)
{
using (WorkManagerDbContext dbContext = IdbContextFactory.CreateDbContext())
{
return dbContext.TaskSet.AsQueryable().Where(s => s.TaskGroup.Id == taskGroupId).
Where(s => s.State.Name == kanbanStateName).AsAsyncEnumerable();
}
}
有效 解决方案,但我不知道它是否是好的解决方案。
public IAsyncEnumerable<TaskEntity> GetTasksByTaskGroupIdAndKanbanStateAsync(Guid taskGroupId, string kanbanStateName, CancellationToken token)
{
using (WorkManagerDbContext dbContext = IdbContextFactory.CreateDbContext())
{
return dbContext.TaskSet.AsQueryable().Where(s => s.TaskGroup.Id == taskGroupId)
.Where(s => s.State.Name == kanbanStateName).ToList().ToAsyncEnumerable();
}
}
发生这种情况是因为 .ToAsyncEnumerable() 将在您使用对象(延迟加载)时执行数据库调用。 ToList() 将立即执行数据库调用。因此,当您在 using 语句中使用它时,DbContext 会在 return 对象被 returned 时被释放。 .ToList() 是这种情况下的正确解决方案。
但是,我对您创建和处理 DbContext 的方法表示怀疑,因为它可能会在以后导致其他问题(例如更新在另一个上下文实例中跟踪的对象等)。你也会失去一些好处,比如结果缓存。