2012-03-07 2 views
5

현재 EF4.3 및 코드 우선을 사용하고 있습니다. 내 개체의 생성은 (내 견해를 통해 - 자동 생성 된 Create를 사용하여) 작동하지만, 개체를 편집하려고 시도하면 변경 사항이 저장되지 않으므로 내 탐색 속성에 다시 연결됩니다. 나는 reading on relationships 이었지만 관계가 변경되었다는 사실을 내 상황에 알리는 방법을 모르겠다.엔티티 프레임 워크의 탐색 속성 업데이트 관계를 가져올 수 없습니다.

다음은 구현 예입니다. 내 프로젝트 개체 내에서

[HttpPost] 
    public ActionResult Edit(ProjectViewModel projectViewModel) 
    { 
     if (ModelState.IsValid) 
     { 
      Project project = new Project(); 
      project.ProjectID = projectViewModel.ProjectID; 
      project.Name = projectViewModel.Name; 
      project.ProjectManager = repository.GetUser(projectViewModel.ManagerID); 
      repository.InsertOrUpdateProject(project); 
      repository.Save(); 
      return RedirectToAction("Index"); 
     } 
     ViewBag.Manager = new SelectList(repository.GetUsers(), "UserID", "FullName", projectViewModel.ManagerID); 
     return View(projectViewModel); 
    } 

: 여기

public class Project 
{ 
    public int ProjectID { get; set; } 
    [Required] 
    public string Name { get; set; } 

    // Navigation Properties 
    public virtual User Manager { get; set; } 
} 

저장소에서 해당 방법이다 (내 컨텍스트 여기
@* Snippet from my view where I link into my ViewModel. *@ 
<div class="row"> 
    <div class="editor-label"> 
     @Html.LabelFor(model => model.ManagerID) 
    </div> 
    <div class="editor-field"> 
     @Html.DropDownListFor(model => model.ManagerID, ViewBag.Manager as SelectList, String.Empty) 
     @Html.ValidationMessageFor(model => model.ManagerID) 
    </div> 
</div> 

내 컨트롤러 구현 (내 편집의 POST)입니다 상주) :

public void InsertOrUpdateProject(Project project) 
    { 
     if (program.ProjectID == default(int)) 
     { 
      context.Projects.Add(project); 
     } 
     else 
     { 
      context.Entry(project).State = EntityState.Modified; 
     } 
    } 

이 속성은 내 속성을 업데이트하는 작업을 수행하지만 내 탐색 속성 (이 경우 Manager)은 업데이트하지 않습니다. 어떤 도움을 주시면 감사하겠습니다.

답변

11

상태를 Modified으로 설정하면 탐색 속성이 아닌 수정 된 스칼라 속성 만 표시됩니다.

  • 해킹은 (당신이 그것을 좋아하지 않을 것이다)

    //... 
    else 
    { 
        var manager = project.Manager; 
        project.Manager = null; 
        context.Entry(project).State = EntityState.Modified; 
        // the line before did attach the object to the context 
        // with project.Manager == null 
        project.Manager = manager; 
        // this "fakes" a change of the relationship, EF will detect this 
        // and update the relatonship 
    } 
    
  • 새로 고침 (열망로드)를 포함하여 데이터베이스 에서 프로젝트의 현재 매니저 : 당신은 몇 가지 옵션이 있습니다. 그런 다음 속성을 설정하십시오. 변경 추적은 관리자의 변경 사항을 다시 감지하고 UPDATE를 작성합니다.

  • 은 모델에 Manager 탐색 속성에 대한 외래 키 속성을 노출 :

    public class Project 
    { 
        public int ProjectID { get; set; } 
        [Required] 
        public string Name { get; set; } 
    
        public int ManagerID { get; set; } 
        public virtual User Manager { get; set; } 
    } 
    

    지금 ManagerID 스칼라 재산 및 Modified에 상태를 설정하면이 속성을 포함합니다.

    Project project = new Project(); 
    project.ProjectID = projectViewModel.ProjectID; 
    project.Name = projectViewModel.Name; 
    project.ManagerID = projectViewModel.ManagerID; 
    repository.InsertOrUpdateProject(project); 
    repository.Save(); 
    
    은 몇 가지 옵션이 여기에 있습니다
+0

우수에 대한 업데이트를 확인하십시오. 고맙습니다. 나는 원래 외래 키 라우트를 수행했지만 그로 인해 몇 가지 문제가있었습니다. 밝혀졌지만, 제대로 작동하려면 네비게이션 속성으로 [ForeignKey ("Name")] 특성을 정의해야했습니다. 당신의 대답을 수락하십시오. 감사! – glockman

+0

@ user1240560 : 내 대답에 이름이 실제로 ForeignKey 특성 (이름 규칙에 따라 FK 검색)없이 작동해야합니다. 그러나 귀하의 이름이 매우 다를 경우 국제 대회 규칙을 따르지 않으면 네, 주석이 필요합니다. – Slauma

+0

@Slauma 당신을 사랑합니다. 다른 접근법은 코드 퍼스트 모델로 작동해야하지만, 데이터베이스를 사용하십시오. 나를 위해 일한 유일한 것은 당신의 해킹이었습니다. 나는 며칠 동안 그것을 망쳤습니다. 그리고 지금 나는 사랑한다고 말하고 있습니다. 너 너무 많아. –

-2

네비게이션 속성의 의미를 정확히 모르겠습니다. 외래 키 관계와 같은 의미입니까? 그렇다면 다음 데이터 주석을 시도하십시오.

public class Project 
{ 
    public int ProjectID { get; set; } 

    [Required] 
    public string Name { get; set; } 

    [ForeignKey("YourNavigationProperty")] 
    public virtual UserManager { get; set; } 
} 

EF 컨텍스트를 업데이트하고 어떤 일이 발생하는지 확인하십시오.

UPDATE 경우 작동

public class Project 
{ 
    public int ProjectID { get; set; } 

    [Required] 
    public string Name { get; set; } 

    [ForeignKey("ManagerId")] 
    public ManagerModel UserManager { get; set; } 
} 

public class ManagerModel 
{ 
    [Key] 
    public int ManagerId { get; set; } 

    public String ManagerName { get; set; } 
} 

참조?

+0

따라서 FK 이름을 명시 적으로 정의하지 않았습니다. 내 Manager 값을 새로운 Manager (작동하는 것처럼 보임)로 설정할 수 있지만 SaveChanges()를 호출하면 실제로 변경 사항이 데이터베이스에 유지되지 않습니다. 그 일을 어떻게해야할지 모르겠습니다. – glockman

+0

내 대답 – jacqijvv

2

, 내가 그들의 3 나열됩니다 : 또한 당신은 당신이 당신의보기에서 얻을 ID를 할당 할 수 있습니다, 데이터베이스에서 Manager 사용자를로드 할 필요가 없습니다 :

옵션 1 :

GraphDiff

를 사용 *이 true로 설정하여 컨텍스트의 Configuration.AutoDetectChangesEnabled 필요가있다. GraphDiff에 대한 자세한 내용은 here 보일를 들어

그냥

Install-Package RefactorThis.GraphDiff 

그런

using (var context = new Context()) 
{ 
    var customer = new Customer() 
    { 
     Id = 12503, 
     Name = "Jhon Doe", 
     City = new City() { Id = 8, Name = "abc" } 
    }; 

    context.UpdateGraph(customer, map => map.AssociatedEntity(p => p.City)); 
    context.Configuration.AutoDetectChangesEnabled = true; 

    context.SaveChanges(); 
} 

NuGet

와 GraphDiff를 설치합니다.

옵션 2 : 찾기 및 편집

컨텍스트에 추적 EF하여 엔티티를 검색. 그런 다음 속성을 편집하십시오.

*이 경우 문맥의 Configuration.AutoDetectChangesEnabled이 true로 설정되어 있어야합니다.

var customer = new Customer() 
{ 
    Id = 12503, 
    Name = "Jhon Doe", 
    City = new City() { Id = 8, Name = "abc" } 
}; 

using (var context = new Contexto()) 
{ 
    var customerFromDatabase = context.Customers 
             .Include(x => x.City) 
             .FirstOrDefault(x => x.Id == customer.Id); 

    var cityFromDataBase = context.Cities.FirstOrDefault(x => x.Id == customer.City.Id); 

    customerFromDatabase.Name = customer.Name; 
    customerFromDatabase.City = cityFromDataBase;     

    context.Configuration.AutoDetectChangesEnabled = true; 
    context.SaveChanges(); 
} 

옵션 3 : 성능이의 문제에서 스칼라 특성

를 사용하는 가장 좋은 방법이지만, 데이터베이스 문제와 그것을 엉망 클래스. Id를 매핑하는 스칼라 (프리미티브) 속성을 만들어야하기 때문에.

* 이렇게하면 Configuration.AutoDetectChangesEnabled을 true로 설정할 필요가 없습니다. 또한 엔티티를 검색하기 위해 데이터베이스에 대한 쿼리를 수행 할 필요가 없습니다 (처음 두 옵션은 그렇습니다 - 예 GraphDiff는 배후에 있습니다!).

var customer = new Customer() 
{ 
    Id = 12503, 
    Name = "Jhon Doe", 
    City_Id = 8, 
    City = null 
}; 

using (var contexto = new Contexto()) 
{ 
    contexto.Entry(customer).State = EntityState.Modified; 
    contexto.SaveChanges(); 
} 
관련 문제