2012-11-15 33 views
8

Giả sử tôi có các lớp mô hình sau đây trong một thiết lập Entity Framework Code-First:cập nhật các đối tượng bị ngắt kết nối với nhiều-nhiều mối quan hệ

public class Person 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    public virtual ICollection<Team> Teams { get; set; } 
} 

public class Team 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    public virtual ICollection<Person> People { get; set; } 
} 

Cơ sở dữ liệu được tạo ra từ mã này bao gồm một bảng TeamPersons, đại diện cho nhiều -to-nhiều mối quan hệ giữa con người và các đội.

Giả sử tôi có đối tượng Person bị ngắt kết nối (không phải proxy và chưa đính kèm ngữ cảnh) có bộ sưu tập Nhóm chứa một hoặc nhiều đối tượng Nhóm bị ngắt kết nối, tất cả đều đại diện cho Nhóm đã có trong cơ sở dữ liệu. Một đối tượng như sẽ được tạo ra bởi những điều sau đây, chỉ là ví dụ, nếu một người nào có ID 1 và một đội với Id 3 đã tồn tại trong db:

var person = new Person 
{ 
    Id = 1, 
    Name = "Bob", 
    Teams = new HashSet<Team> 
    { 
     new Team { Id = 3, Name = "C Team"} 
    } 
}; 

cách tốt nhất để cập nhật đối tượng này là gì, để sau khi cập nhật bảng TeamPersons chứa một hàng duy nhất cho Bob, liên kết anh ta với C Team? Tôi đã thử điều hiển nhiên:

using (var context = new TestContext()) 
{ 
    context.Entry(person).State = EntityState.Modified; 
    context.SaveChanges(); 
} 

nhưng bộ sưu tập Nhóm chỉ bị bỏ qua bởi điều này. Tôi cũng đã thử nhiều thứ khác, nhưng dường như không có gì làm chính xác những gì tôi đang ở đây. Cảm ơn vì bất kì sự giúp đỡ.

EDIT:

Vì vậy, tôi nhận được rằng tôi có thể lấy cả hai người và Nhóm [s] từ db, cập nhật chúng và sau đó cam kết thay đổi:

using (var context = new TestContext()) 
{ 
    var dbPerson = context.People.Find(person.Id); 
    dbPerson.Name = person.Name; 
    dbPerson.Teams.Clear(); 
    foreach (var id in person.Teams.Select(x => x.Id)) 
    { 
     var team = context.Teams.Find(id); 
     dbPerson.Teams.Add(team); 
    } 

    context.SaveChanges(); 
} 

Đây là một nỗi đau Tuy nhiên, nếu thực thể phức tạp của một người. Tôi biết tôi có thể sử dụng Automapper hoặc một cái gì đó để làm cho mọi việc dễ dàng hơn một chút, nhưng vẫn có vẻ xấu hổ nếu không có cách nào để cứu đối tượng ban đầu, thay vì phải lấy một cái mới và sao chép tất cả các thuộc tính qua ...

Trả lời

1

Cách tiếp cận chung là tìm nạp Team từ cơ sở dữ liệu và Add mà đến bộ sưu tập của Teams. Đặt EntityState.Modified chỉ ảnh hưởng đến thuộc tính vô hướng, chứ không ảnh hưởng đến thuộc tính điều hướng.

+0

Mua bản thân, điều này dường như không làm việc: thêm một đội lấy từ db để một người mà không phải là một proxy vẫn không có cập nhật cho bảng TeamPersons. Công việc gì đang tìm nạp cả Nhóm và Người từ db (vì vậy Person là một proxy), nhưng sau đó bạn phải cập nhật Người đã tìm nạp này để phù hợp với Người đang được lưu ... – Duncan

+1

Ah, bạn nói đúng (nên đã đọc tốt hơn). Sau khi chỉnh sửa: bạn có thể sử dụng 'DbContext.Entry (dbPerson) .CurrentValues.SetValues ​​(person)'. –

+0

Cảm ơn, đó là hữu ích - Tôi không biết về CurrentValues.SetValues ​​ – Duncan

0

Hãy thử chọn các thực thể hiện có trước, sau đó đính kèm nhóm vào bộ sưu tập nhóm của đối tượng người đó.

Cái gì đó như thế này: (cú pháp có thể không được chính xác đúng)

using (var context = new TestContext()) 
{ 
    var person = context.Persons.Where(f => f.Id == 1).FirstOrDefault(); 
    var team = context.Teams.Where(f => f.Id == 3).FirstOrDefault(); 

    person.Teams.Add(team); 

    context.Entry(person).State = EntityState.Modified; 
    context.SaveChanges(); 
} 
+0

Cảm ơn, nhưng sau đó tôi phải cập nhật người mới này từ bản gốc mà tôi muốn lưu (xem bản chỉnh sửa của tôi) - Tôi hy vọng sẽ có cách khác. – Duncan

+0

Được rồi, vậy bạn đang nói có nhiều thay đổi đối tượng người bị ngắt kết nối? – EkoostikMartin

+0

Có khả năng, có: Tôi muốn biết cách tốt nhất để cập nhật db từ đối tượng Person bị ngắt kết nối, khi không biết thuộc tính nào của đối tượng đó đã bị thay đổi. – Duncan

0

Đó là nơi EF s ks **. rất không hiệu quả cho kịch bản bị ngắt kết nối. tải dữ liệu cho bản cập nhật/xóa và mọi thứ để cập nhật lại, người ta không thể chỉ gắn thực thể được cập nhật vào ngữ cảnh như một thực thể có cùng khóa có thể đã tồn tại trong ngữ cảnh, trong trường hợp đó, EF sẽ chỉ ném lên. những gì cần phải được thực hiện là để kiểm tra xem một thực thể với cùng một khóa đã có trong bối cảnh và đính kèm hoặc cập nhật cho phù hợp. còn tệ hơn khi cập nhật thực thể với nhiều mối quan hệ con. loại bỏ trẻ em bị xóa là từ bộ thực thể của trẻ nhưng không phải là tài sản tham chiếu, nó rất lộn xộn.

0

Bạn có thể sử dụng phương thức Đính kèm.Hãy thử điều này:

using (var context = new TestContext()) 
{ 
    context.People.Attach(person); 

    //i'm not sure if this foreach is necessary, you can try without it to see if it works 
    foreach (var team in person.Teams) 
    { 
     context.Teams.Attach(team); 
    } 

    context.Entry(person).State = EntityState.Modified; 

    context.SaveChanges(); 
} 

tôi đã không kiểm tra mã này, cho tôi biết nếu bạn có bất kỳ vấn đề

Các vấn đề liên quan