我在 asp.net mvc 应用程序中处理 Entity Framework 连接时遇到奇怪的问题。
我有简单的结构,例如:
实体 :
public class EmployeeReport
{
public int EmployeeReportId { get; set; }
public DateTime Created { get; set; }
public Decimal Hours { get; set; }
public string Comment { get; set; }
public int EmployeeId { get; set; }
public int ContractId { get; set; }
public int ServiceId { get; set; }
public virtual ReportContract Contract { get; set; }
public virtual ReportService Service { get; set; }
public virtual Employee Employee { get; set; }
}
实体映射器:
public class EmployeeReportMapper : EntityTypeConfiguration<EmployeeReport>
{
public EmployeeReportMapper()
{
ToTable("intranet_employee_reports");
HasKey(x => x.EmployeeReportId);
Property(x => x.Created).HasColumnName("Created").IsRequired();
Property(x => x.Comment).HasColumnName("Comment").IsOptional();
Property(x => x.Hours).HasColumnName("Hours").IsRequired();
HasRequired(x => x.Employee).WithMany().HasForeignKey(x => x.EmployeeId);
HasRequired(x => x.Service).WithMany().HasForeignKey(x => x.ServiceId);
HasRequired(x => x.Contract).WithMany().HasForeignKey(x => x.ServiceId);
}
}
DbContext - 接口(interface)
public interface IDbContext : IDisposable
{
IDbSet<EmployeeReport> EmployeeReports { get; }
}
DbContext - 实现
public class IntranetDbContext : DbContext,IDbContext
{
public IDbSet<EmployeeReport> EmployeeReports { get; set; }
...
public IntranetDbContext() : base("IntranetDb")
{
Database.SetInitializer<IntranetDbContext>(null);
}
public void Commit()
{
SaveChanges();
}
public void ChangeEntityState(object entity, EntityState entityState)
{
Entry(entity).State = entityState;
}
public void ExecuteSql(string query, SqlParameterCollection parameterCollection)
{
Database.ExecuteSqlCommand(query, parameterCollection);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
/* Register custom mapping class */
modelBuilder.Configurations.Add(new EmployeeReportMapper());
....
base.OnModelCreating(modelBuilder);
}
}
最后我的结构图配置:
public class CoreRegistry : Registry
{
public CoreRegistry()
{
For<IDbContext>().HttpContextScoped().Use<IntranetDbContext>();
...
}
}
和 Global.asax :
protected void Application_EndRequest(object sender, EventArgs e)
{
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}
好的,现在的问题是,在我的应用程序中,我使用标准的构造函数依赖注入(inject)
或调用 ObjectFactory.GetInstance()。
在我的一个 Controller 中,我调用了服务类,它可以访问 dbcontext 并获取一些实体。
不幸的是我得到了经典的异常(exception):
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
这很奇怪,因为在请求期间调用了服务,并且所有数据都被强制发送到 Controller 中的客户端......
任何想法,我在哪里做错了?
编辑 :
服务代码:
public class EmployeeService : IEmployeeService
{
/// <summary>
/// IDbContext reference
/// </summary>
private readonly IDbContext _dbContext;
public EmployeeService(IDbContext dbContext)
{
_dbContext = dbContext;
}
public List<Employee> GetSubordinateEmployees(Employee employee)
{
List<Employee> employees = new List<Employee>();
foreach (var unit in employee.OrganizationUnits.ToList()) /* throw exception*/
{
foreach (var childrenUnit in unit.ChildrenUnits)
{
employees.AddRange(childrenUnit.Employees);
}
}
return employees.Distinct().ToList();
}
Controller :
private readonly IEmployeeService _employeeService;
public EmployeeReportController(IEmployeeService employeeService)
{
_employeeService = employeeService;
}
[HttpGet]
public ActionResult SearchReports()
{
List<Employee> employees = _employeeService.GetSubordinateEmployee(IntranetSession.Current.LoggedAccount.Employee).ToList(); // Exception!
...
return View();
}
}
最佳答案
您的代码不使用当前 DbContext
一点也不。问题是:
IntranetSession.Current.LoggedAccount.Employee
其次是:
employee.OrganizationUnits.ToList()
您存储在 session 中的员工加载了已经处理的上下文,但它仍然保持对该上下文的引用。当您加载该员工时,您并不急于加载他的组织,因此一旦您访问她
OrganizationUnits
它将尝试在已处置的上下文中触发延迟加载。有两种方法可以避免这个问题:
context.Employees.Include(e => e.OrganizationUnits).Single(...)
这样的员工如果您想在 session 中缓存整个员工,请确保您将通过调用禁用 session 中存储的对象的代理创建:
context.Configuration.ProxyCreationEnabled = false;
它将确保缓存的数据不会保留对已处理上下文的引用(顺便说一句,这会阻止垃圾收集器收集上下文及其所有引用的对象)。
关于entity-framework - Entity Framework 上下文和结构图配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7341141/