2012-03-07 21 views
5

Tôi hiện đang sử dụng EF4.3 và Mã đầu tiên. Việc tạo các đối tượng của tôi hoạt động (thông qua quan điểm của tôi - chỉ sử dụng Create được tạo tự động), nhưng khi tôi cố gắng chỉnh sửa một đối tượng, nó không lưu bất kỳ thay đổi nào, hoàn toàn, buộc trở lại các thuộc tính điều hướng của tôi. Tôi đã được reading on relationships, nhưng tôi không hiểu làm thế nào để nói với bối cảnh của tôi rằng mối quan hệ đã thay đổi.Không thể liên hệ cập nhật cho thuộc tính điều hướng trong khung tổ chức

Dưới đây là một số mã ví dụ về việc triển khai của tôi.

@* 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> 

Đây là thực hiện của tôi Controller (POST của Chỉnh sửa của tôi):

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

Trong đối tượng dự án của tôi:

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

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

Dưới đây là phương pháp tương ứng từ kho (nơi bối cảnh của tôi cư trú):

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

Chỉ cần được rõ ràng, điều này không làm việc để cập nhật tài sản của tôi, nhưng nó không cập nhật thuộc tính chuyển hướng của tôi (trong trường hợp này, Manager). Đánh giá cao bất kỳ trợ giúp nào.

Trả lời

11

Đặt trạng thái thành Modified chỉ đánh dấu thuộc tính vô hướng là thuộc tính điều hướng, không phải điều hướng. Bạn có một vài lựa chọn:

  • Một hack (bạn sẽ không thích nó)

    //... 
    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 
    } 
    
  • Nạp lại dự án từ cơ sở dữ liệu bao gồm (tải háo hức) người quản lý hiện hành. Sau đó thiết lập các thuộc tính. Thay đổi theo dõi sẽ phát hiện một sự thay đổi của người quản lý một lần nữa và viết một UPDATE.

  • Expose một tài sản quan trọng nước ngoài cho các tài sản Manager hải trong mô hình của bạn:

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

    Bây giờ ManagerID là một tài sản vô hướng và thiết lập nhà nước để Modified sẽ bao gồm khách sạn này.Hơn nữa, bạn không cần phải tải người sử dụng quản lý từ cơ sở dữ liệu, bạn chỉ có thể gán ID bạn nhận được từ quan điểm của bạn:

    Project project = new Project(); 
    project.ProjectID = projectViewModel.ProjectID; 
    project.Name = projectViewModel.Name; 
    project.ManagerID = projectViewModel.ManagerID; 
    repository.InsertOrUpdateProject(project); 
    repository.Save(); 
    
+0

Tuyệt vời. Cảm ơn bạn. Ban đầu tôi đã thực hiện các tuyến đường chính nước ngoài, nhưng đã có một số vấn đề với nó. Hóa ra, nó hoạt động, nhưng tôi phải định nghĩa thuộc tính [ForeignKey ("Name")] với thuộc tính navigation cho mọi thứ để ánh xạ đúng cách. Chấp nhận câu trả lời của bạn. Cảm ơn! – glockman

+0

@ user1240560: Với tên trong câu trả lời của tôi, nó thực sự nên hoạt động mà không có thuộc tính ForeignKey (phát hiện FK theo quy ước tên). Nhưng nếu tên của bạn hơi khác một chút và không tuân thủ các quy tắc quy ước, thì có, bạn cần chú thích. – Slauma

+0

@ Slauma Tôi yêu bạn, các cách tiếp cận khác nên làm việc với Code First Model, nhưng với một DataBase đầu tiên chỉ có một mà làm việc cho tôi là hack của bạn, tôi đã rối tung với nó trong nhiều ngày, và bây giờ tôi phải nói rằng tôi yêu bạn rất nhiều –

-2

Tôi không chắc chắn chính xác ý bạn là gì bởi các thuộc tính điều hướng? Bạn có ý nghĩa như một mối quan hệ chính nước ngoài? Nếu vậy, hãy thử chú thích dữ liệu sau:

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

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

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

Cập nhật EF Bối cảnh của bạn và xem điều gì sẽ xảy ra?

CẬP NHẬT

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

Xem nếu mà làm việc?

+0

Vì vậy, tôi không xác định rõ ràng tên FK của mình. Tôi muốn có thể thiết lập giá trị Manager của tôi cho một Manager mới (có vẻ như hoạt động) nhưng những thay đổi này không thực sự bền bỉ đến cơ sở dữ liệu khi tôi gọi SaveChanges(). Tôi không chắc làm thế nào để điều đó xảy ra. – glockman

+0

Xem bản cập nhật cho câu trả lời của tôi – jacqijvv

2

Có một số tùy chọn ở đây, tôi sẽ liệt kê 3 trong số họ:

Lựa chọn 1: Sử dụng GraphDiff

* Điều này cần sự Configuration.AutoDetectChangesEnabled của ngữ cảnh của bạn thiết lập là true.

Chỉ cần cài đặt GraphDiff với NuGet

Install-Package RefactorThis.GraphDiff 

Sau đó

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

Để biết thêm chi tiết về GraphDiff trông here.

Tùy chọn 2: Tìm và chỉnh sửa

Tìm kiếm thực thể của bạn với EF để theo dõi nó theo ngữ cảnh. Sau đó chỉnh sửa các thuộc tính.

* Điều này cần Configuration.AutoDetectChangesEnabled ngữ cảnh của bạn được đặt thành 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(); 
} 

Lựa chọn 3: Sử dụng một tài sản

vô hướng Trong một vài buổi biểu diễn này là cách tốt nhất, nhưng nó lộn xộn lớp học của bạn với mối quan tâm cơ sở dữ liệu. Vì bạn sẽ cần phải tạo thuộc tính vô hướng (nguyên thủy) để ánh xạ Id.

* Bằng cách này, bạn không cần phải đặt Configuration.AutoDetectChangesEnabled thành true. Và bạn cũng sẽ không cần phải thực hiện một truy vấn tới cơ sở dữ liệu để lấy ra các thực thể (như hai tùy chọn đầu tiên sẽ làm - có GraphDiff thực hiện nó đằng sau hậu trường!).

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(); 
} 
Các vấn đề liên quan