2012-07-08 11 views
6

Tôi đã pored thông qua StackOverflow, Google và asp.net cố gắng để tìm một cắt rõ ràng, ví dụ cơ bản của làm thế nào để làm điều này. Tất cả các ví dụ đã được trừu tượng hoặc liên quan đến biến chứng không áp dụng. Tôi đã không thể trích xuất nhiều hữu ích từ họ. Cho đến nay, không ai trong số họ hoàn toàn trả lời câu hỏi của tôi hoặc giải quyết (các) vấn đề của tôi.Làm thế nào để cập nhật/tạo dữ liệu quan hệ nhiều-nhiều trong Mã MVC-lần đầu tiên sử dụng EF?

tôi đang làm việc trên một dự án MVC với mô hình sau:

Article.cs:

public class Article 
{ 

    public int ArticleId { get; set; } 
    public string Title { get; set; } 
    . 
    . 
    . 
    public virtual ICollection<Category> Categories { get; set; } 

    public Article() 
    { 
     Categories = new HashSet<Category>(); 
    } 
} 

Category.cs:

public class Category 
{ 
    public int CategoryId { get; set; } 
    public string Name { get; set; } 

    public virtual ICollection<Article> Articles { get; set; } 

    public Category() 
    { 
     Articles = new HashSet<Article>(); 
    } 
} 

ArticleEntities.cs:

public class ArticleEntities : DbContext 
{ 
    public DbSet<Article> Articles { get; set; } 
    public DbSet<Category> Categories { get; set; } 

} 

Nghệ thuật icle có thể có nhiều loại và một danh mục có thể thuộc về nhiều bài viết.

Cho đến nay tôi có thể lưu/cập nhật/tạo tất cả các trường bài viết ngoại trừ Danh mục.

Tôi đại diện cho họ dưới dạng hộp kiểm trong chế độ xem. Tôi có thể nhận được các giá trị cho các hộp kiểm đã chọn vào bộ điều khiển, nhưng, mọi nỗ lực tôi đã thực hiện để lưu trữ chúng trong db với bài viết đã thất bại.

Làm thế nào để:

1) Khi lưu một bài báo đã chỉnh sửa, cập nhật các mối quan hệ hiện có trong bảng quan hệ mà không cần tạo bản sao?

2) Khi lưu một bài viết mới, hãy tạo các mối quan hệ đã chọn trong bảng quan hệ?

Trả lời

9

Tôi giả định rằng bạn nhận được danh sách CategoryId s từ hành động của bộ điều khiển, một số List<int> hoặc tổng quát hơn chỉ là IEnumerable<int>.

1) Khi lưu bài viết đã chỉnh sửa, hãy cập nhật quan hệ hiện có trong bảng quan hệ mà không tạo bản sao?

Article article; // from post action parameters 
IEnumerable<int> categoryIds; // from post action parameters 

using (var ctx = new MyDbContext()) 
{ 
    // Load original article from DB including its current categories 
    var articleInDb = ctx.Articles.Include(a => a.Categories) 
     .Single(a => a.ArticleId == article.ArticleId); 

    // Update scalar properties of the article 
    ctx.Entry(articleInDb).CurrentValues.SetValues(article); 

    // Remove categories that are not in the id list anymore 
    foreach (var categoryInDb in articleInDb.Categories.ToList()) 
    { 
     if (!categoryIds.Contains(categoryInDb.CategoryId)) 
      articleInDb.Categories.Remove(categoryInDb); 
    } 

    // Add categories that are not in the DB list but in id list 
    foreach (var categoryId in categoryIds) 
    { 
     if (!articleInDb.Categories.Any(c => c.CategoryId == categoryId)) 
     { 
      var category = new Category { CategoryId = categoryId }; 
      ctx.Categories.Attach(category); // this avoids duplicate categories 
      articleInDb.Categories.Add(category); 
     } 
    } 

    ctx.SaveChanges(); 
} 

Lưu ý rằng mã cũng làm việc khi bạn có một ArticleViewModel thay vì một Article, cho rằng các tên thuộc tính đều giống nhau (SetValues mất một tùy object).

2) Khi lưu một bài viết mới, hãy tạo các mối quan hệ đã chọn trong mối quan hệ bảng?

Nhiều hay ít ý tưởng tương tự như trên nhưng đơn giản hơn vì bạn không cần phải so sánh với tình trạng ban đầu trong cơ sở dữ liệu:

Article article; // from post action parameters 
IEnumerable<int> categoryIds; // from post action parameters 

using (var ctx = new MyDbContext()) 
{ 
    foreach (var categoryId in categoryIds) 
    { 
     var category = new Category { CategoryId = categoryId }; 
     ctx.Categories.Attach(category); // this avoids duplicate categories 
     article.Categories.Add(category); 
     // I assume here that article.Categories was empty before 
    } 
    ctx.Articles.Add(article); 

    ctx.SaveChanges(); 
} 
+0

"Tôi cho rằng bạn có được một danh sách các CategoryIds từ điều khiển bài hành động, một Danh sách hoặc tổng quát hơn chỉ là một số điện thoại có thể truy cập là . – panzerblitzer

+0

Có, tôi là thể loại trong bộ sưu tập (Thực tế, có thể). Mọi thứ có vẻ như nó sẽ hoạt động, nhưng một dòng mã sẽ không biên dịch: "if (! CategoryIds.Bất kỳ (c => c.CategoryId == categoryInDb.CategoryId)) "Tôi gặp lỗi" -'int "không chứa định nghĩa cho CategoryId.- – panzerblitzer

+0

@panzerblitzer: Vâng, đó là một sai lầm, xin lỗi. sửa chữa mã (bằng cách sử dụng 'Chứa', xem ở trên)' if (! categoryIds.Any (c => c == categoryInDb.CategoryId)) 'cũng làm việc tốt. – Slauma