我经历的StackOverflow,谷歌和asp.net钻研试图找到一个明确的,如何做到这一点简单的例子。 所有的例子已不适用的抽象或参与的并发症。 我一直无法从中提取了许多有益的。 到目前为止,他们都没有完全回答我的问题或解决了我的问题(一个或多个)。
我的工作有以下型号的MVC项目:
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; }
}
文章可以有很多种类和类别可以属于很多文章。
到目前为止,我可以保存/更新/创建除类别中的所有项目的字段。
我代表他们作为视图中的复选框。 我可以为选定的复选框的值到控制器,但是,我已经将它们存储在数据库与文章已经失败每一次尝试。
我如何能:
1)当保存编辑后的文章,更新的关系表中的现有关系,而无需创建重复?
2)当保存一个新的文章,请在关系表中选择的关系?
我假设你的列表CategoryId
从控制器后动作S,一个List<int>
或更一般只是一个IEnumerable<int>
。
1)当保存编辑后的文章,更新的关系表中的现有关系,而无需创建重复?
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();
}
需要注意的是,代码也可以当你有一个ArticleViewModel
代替的Article
,因为属性名称是相同的( SetValues
接受一个任意的object
)。
2)当保存一个新的文章,请在关系表中选择的关系?
或多或少相同的思路之上,但简单,因为你并不需要在数据库中的原始状态进行比较:
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();
}
文章来源: How to update/create many-to-many relational data in MVC Code-first using EF?