3

asp.net mvc 응용 프로그램에서 엔티티 프레임 워크 연결을 삭제하는 데 이상한 문제가 있습니다.엔티티 프레임 워크 컨텍스트 및 구조 맵 처리

엔티티 :

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 interface IDbContext : IDisposable 
{ 
    IDbSet<EmployeeReport> EmployeeReports { get; } 
} 

DbContext -

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을 구현

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(); 
    } 

좋아, 이제 문제, 내 응용 프로그램에서 내가 사용하여 표준 생성자 의존성 주입 또는 전화 ObjectFactory.GetInstance().

내 컨트롤러 중 하나에서 dbcontext에 액세스 할 수 있고 일부 entite를 가져 오는 서비스 클래스를 호출합니다.

불행하게도 나는 고전적인 예외를 얻을 :

ObjectContext는 인스턴스가 배치되어 더 이상 연결이 필요한 작업 을 사용할 수 없습니다.

서비스를 요청하는 동안 호출되고 모든 데이터가 컨트롤러의 클라이언트에 강제되어 있기 때문이 이상하다 ...

내가 실수 할 어떤 생각?

편집 :

서비스 코드 :

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(); 
    } 

컨트롤러 :

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(); 
    } 


} 
+0

실제로 예외가 throw되는 코드와 실제로 ObjectContext를 사용하는 코드를 표시하십시오. –

+0

컨트롤러 및 서비스 코드가 추가되었습니다. – Mennion

답변

1

귀하의 코드에서 현재의 모든 DbContext를 사용하지 않습니다. 문제는 :

IntranetSession.Current.LoggedAccount.Employee 

은 얹는 : 세션에 저장

employee.OrganizationUnits.ToList() 

귀하의 직원이 이미 배치되어 문맥에로드하지만 여전히 그 상황에 대한 참조를 유지합니다. 그 직원을로드했을 때 당신은 자신의 조직에 열중하지 않기를 원했기 때문에 OrganizationUnits에 접속하면 처분 된 컨텍스트에서 느린 로딩을 시도합니다.

이 문제를 방지하는 방법은 두 가지가 있습니다 :

  • 열망로드 당신이 세션에 저장된 직원에서 사용하는 데 필요한 모든 정보를 제공합니다. 그것은 당신이 세션에서 전체 직원을 캐시 할 당신이에 저장된 객체에 대한 프록시 생성을 비활성화됩니다 있는지 확인하는 경우는

필요 세션 및로드 온 디맨드 데이터 context.Employees.Include(e => e.OrganizationUnits).Single(...)

  • 스토어에만 직원의 ID와 같은 직원을 검색하는 것을 의미 호출하여 세션 :

    context.Configuration.ProxyCreationEnabled = false; 
    

    는 캐시 된 데이터 (. BTW 컨텍스트와 모든 참조 된 객체를 수집 가비지 수집기 않도록) 배치 된 컨텍스트에 참조를 유지하지 않을 보장한다.

  • +0

    내 init 세션 코드에서 include가 포함 된 데이터를 가져 오지만 직원의 조직 단위 가져 오기를 잊어 버렸습니다. 내가 명시 적으로 호출 LoggedAccount.Employee.OrganizationUnits.ToListI(); init 코드에서 응용 프로그램이 작동합니다. 방향에 대해 고마워. – Mennion