操作无法完成,因为 DbContext 已被释放。System.InvalidOperationException
Posted
技术标签:
【中文标题】操作无法完成,因为 DbContext 已被释放。System.InvalidOperationException【英文标题】:The operation cannot be completed because the DbContext has been disposed.System.InvalidOperationException 【发布时间】:2021-03-01 23:54:27 【问题描述】:我使用 N-Layer Architech 和依赖注入。 我还想在员工列表中列出部门列表。
public List<Employee> ListEmployee()
using (var context = new DatabaseContext())
return context.Set<Employee>().Include("Department").ToList();
或者我尝试了两种方法但得到了同样的错误。
public IQueryable<Employee> GetQueryableEmployee()
using (var context = new DatabaseContext())
return context.Set<Employee>().Include("Department").AsQueryable<Employee>();
我像这样创建了我的表。 部门表
public int DepartmentID get; set;
public virtual Department Department get; set;
和员工表
public ICollection<Employee> Employees get; set;
我使用 Fluent Api 创建的一对多关系
modelBuilder.Entity<Employee>()
.HasRequired<Department>(e => e.Department)
.WithMany(c => c.Employees)
.HasForeignKey<int>(e => e.DepartmentID);
员工控制器
public class EmployeeController : Controller
private readonly IEmployeeService _employeeService;
public EmployeeController(IEmployeeService employeeService)
_employeeService = employeeService;
public ActionResult Index()
var employee = _employeeService.ListEmployee();
return View(employee);
和查看
@model IEnumerable<Test.Entities.Concreate.Employee>
@foreach (var item in Model)
<tr>
<td>
@html.DisplayFor(modelItem => item.Department.DepartmentName)
</td>
如何在同一个列表中显示两个表? 我认为需要平衡 DepartmentID 的地方
【问题讨论】:
FiorGetQueryableEmployee
你会有这个例外。因为您已经处理了已生成 IQueryable
的上下文
var employee=_employeeService.GetQueryableEmployee 是这样吗?
是的,这种用法是错误的。您不必每次都创建上下文,而是配置 DI,以便为每个请求创建实例。
builder.RegisterType要利用IQueryable
,至少必须将 DbContext 限定在将引用实体的最外层点。这可以通过依赖注入来管理,前提是 DbContext 的生命周期范围为请求,或者由工作单元模式管理。 (using
块在包含 DbContext 的控制器级别限定了一个工作单元)
根据您的 IoC 容器,上下文可以限定为 PerRequest
之类的内容。以 Autofac 为例:
builder.RegisterType<DatabaseContext>().AsSelf().InstancePerRequest();
使用 Dbcontexts,您可能需要考虑将容器配置为使用特定的 Constructor /w 参数作为连接字符串等。
当 DbContext 本身被提供给您的控制器时,您的存储库 (EmployeeService) 将为要注入的 DbContext 声明一个依赖项。
public class EmployeeService
private readonly DatabaseContext _context = null;
public EmployeeService(DatabaseContext context)
_context = context ?? throw new ArgumentNullException("context");
public IQueryable<Employee> GetEmployees()
return _context.Employees.AsQueryable();
这种存储库方法的优点是您的服务方法只是用于访问数据的包装器。请注意,我没有将.Include()
用于部门,呼叫者可以这样做或根据他们的需要投射员工。
所以在控制器中你可以去:
var employeesWithDepartments = EmployeeService.Employees
.Include(x => x.Department)
.ToList();
或者更好的是,只需将数据投影到您需要的内容上,这将构成一个更简化的查询:
var employeeViewModels = EmployeeService.Employees
.Select(x => new EmployeeViewModel
Name = x.Name,
Department = x.Department.Name,
// ...
).ToList();
使用此模式,您可以将“核心”业务逻辑集中在您的存储库/服务中,例如,如果员工具有您应该始终默认考虑的 IsActive 状态:
public IQueryable<Employee> GetEmployees(bool includeInactive = false)
var query = context.Employees.AsQueryable();
if(!includeInactive)
query = query.Where(x => x.IsActive);
return query;
调用代码可以使用额外的Where
子句进一步过滤数据,使用Select
执行预测,或者只需进行Count
或进行Any
检查,而无需在存储库/服务上使用其他方法。
【讨论】:
解决了我的 Configuration.LazyLoadingEnabled = false;获取列表的问题,但找不到 IQueryable 的解决方案。以上是关于操作无法完成,因为 DbContext 已被释放。System.InvalidOperationException的主要内容,如果未能解决你的问题,请参考以下文章
操作无法完成,因为 DbContext 已使用 MVC 4 处置
注入 DbContext 时无法访问 ASP.NET Core 中已释放的对象
azurew网站持续部署 - Web Deploy无法修改目标上的文件“XXX”,因为它已被外部进程锁定