2012-09-16 45 views
5

Tôi đang sử dụng EF Mã đầu tiên với cấu hình sauCập nhật một nhiều với nhiều bộ sưu tập đầu tiên với mã EF

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    base.OnModelCreating(modelBuilder); 
    modelBuilder.Entity<UserProfile>() 
     .HasMany(x => x.TeamLeaders) 
     .WithMany() 
     .Map(m => m.MapLeftKey("UserId") 
     .MapRightKey("TeamLeaderId") 
     .ToTable("UserTeamLeaders")); 
} 

TeamLeaders là một ICollection CỦA NGƯỜI SỬ DỤNG tức là nó là một tự tham khảo nhiều-nhiều mối quan hệ.

Bằng tiếng Anh đơn giản, người dùng có thể có nhiều hơn một trưởng nhóm. Cấu hình này có vẻ đúng, vì nó tạo ra bảng liên kết FK/PK đấu như tôi mong đợi.

Tôi có ứng dụng MVC4 cho phép chỉnh sửa, thêm và xóa các nhà lãnh đạo nhóm khỏi bộ sưu tập.

Trong điều khiển của tôi, ban đầu tôi đã có những điều sau:

var original = context.UserProfiles 
     .Include("TeamLeaders") 
     .Single(x => x.UserId == model.UserId); 

    context.Entry(original).CurrentValues.SetValues(model); 

Tuy nhiên, đó dòng cuối cùng đã thất bại trong việc đánh dấu các bộ sưu tập TeamLeaders được cập nhật, và khi tôi gọi SaveChanges(), không thay đổi được ghi lại.

Thay vào đó, tôi đã viết một phương pháp CopyProperties đơn giản trên lớp học của tôi dùng, trong đó sử dụng phản ánh để tự sao chép các thuộc tính trên, vì vậy trong điều khiển của tôi bây giờ tôi có:

var original = context.UserProfiles 
     .Include("TeamLeaders") 
     .Single(x => x.UserId == model.UserId); 

    //context.Entry(original).CurrentValues.SetValues(model); 

    original.CopyProperties(model); 

Tuy nhiên, điều này đi quá xa, và SaveChanges cố gắng thêm người dùng mới vào hệ thống khớp với hồ sơ của trưởng nhóm đã chọn.

Có ai có thể tư vấn về phần nào của việc này tôi đang làm sai không? Tôi không chắc liệu tôi có cần cập nhật ánh xạ hay thay đổi cách tôi sao chép thuộc tính từ mô hình chế độ xem sang kiểu

Trả lời

3

Bạn phải sửa đổi bộ sưu tập TeamLeaders đã tải trong người dùng original theo thay đổi của bạn để phát hiện thay đổi có thể nhận ra các nhà lãnh đạo nào đã bị xóa và đã được thêm vào. Khi bạn gọi SaveChanges thì EF sẽ viết các câu lệnh DELETE và INSERT thích hợp cho bảng kết nối dựa trên các thay đổi được phát hiện. Cách đơn giản nhất sẽ giống như sau:

var original = context.UserProfiles 
    .Include("TeamLeaders") 
    .Single(x => x.UserId == model.UserId); 

original.TeamLeaders.Clear(); 
foreach (var teamLeader in model.TeamLeaders) 
{ 
    var user = context.UserProfiles.Find(teamLeader.UserId); 
    if (user != null) 
     original.TeamLeaders.Add(user) 
} 
context.SaveChanges(); 

Find sẽ tìm nạp các nhà lãnh đạo nhóm từ ngữ cảnh nếu chúng đã được tải. Nếu chúng không được tải, nó sẽ truy vấn cơ sở dữ liệu.

Nếu bạn muốn tránh các truy vấn bổ sung mà bạn có thể đính kèm các nhà lãnh đạo đội bóng bằng tay với bối cảnh:

var original = context.UserProfiles 
    .Include("TeamLeaders") 
    .Single(x => x.UserId == model.UserId); 

original.TeamLeaders.Clear(); 
foreach (var teamLeader in model.TeamLeaders) 
{ 
    var user = context.UserProfiles.Local 
     .SingleOrDefault(o => o.UserId == teamLeader.UserId); 
    if (user == null) 
    { 
     user = new User { UserId = teamLeader.UserId }; 
     context.UserProfiles.Attach(user); 
    } 
    original.TeamLeaders.Add(user) 
} 
context.SaveChanges(); 

Trừ truy vấn đầu tiên để nạp original ở đây là không có truy vấn cơ sở dữ liệu tiếp tục tham gia.

BTW: Bạn sẽ có thể sử dụng mạnh mẽ gõ Include phiên bản với EF Mã đầu tiên:

Include(u => u.TeamLeaders) 

Bạn chỉ cần using System.Data.Entity; trong tập tin mã của bạn để có được quyền truy cập vào phiên bản này.

+0

Cảm ơn bạn vì điều này - hoạt động một điều trị. Tôi có thể không muốn phải xóa/thêm lại trong bộ điều khiển - thay vào đó nó sẽ là tốt đẹp nếu có một cách để thiết lập nó để nó hoạt động cho chính nó với một số cấu hình/thuộc tính đơn giản trên mô hình/ánh xạ , nhưng điều này làm việc vì vậy tôi sẽ gắn bó với điều này cho bây giờ. – GGG

+0

@GGG: Thật không may khi cập nhật biểu đồ đối tượng tách rời luôn luôn là một chút mã để viết.Không có tùy chọn cấu hình nào sẽ đơn giản hóa công việc. 'CurrentValues.SetValues ​​(model)' chỉ ảnh hưởng đến các thuộc tính vô hướng, nó không cập nhật bất kỳ thuộc tính điều hướng nào, như bạn đã thấy trong lần thử đầu tiên của mình. – Slauma

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