c# - 如何使用 EF 在 MVC Code-first 中更新/创建多对多关系数据?

标签 c# asp.net-mvc asp.net-mvc-3 entity-framework many-to-many

我仔细研究了 StackOverflow、Google 和 asp.net,试图找到一个清晰的基本示例来说明如何执行此操作。所有示例都是抽象的或涉及不适用的并发症。我没能从中提取出多少有用的信息。到目前为止,他们都没有完全回答我的问题或解决我的问题。

我正在使用以下模型开发 MVC 项目:

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

类别.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; }

}

一篇文章可以有多个分类,一个分类可以属于多篇文章。

到目前为止,我可以保存/更新/创建除类别之外的所有文章字段。

我将它们表示为 View 中的复选框。我可以将所选复选框的值获取到 Controller 中,但是,我为将它们与文章一起存储在数据库中所做的每一次尝试都失败了。

我如何:

1) 保存已编辑的文章时,更新关系表中的现有关系而不创建重复项?

2)保存新文章时,在关系表中创建选择的关系?

最佳答案

我假设您得到了 CategoryId 的列表s 来自 Controller 后操作,a List<int>或者更一般的只是一个 IEnumerable<int> .

1) When saving an edited article, update the existing relations in the relation table without creating duplicates?

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) When saving a new article, create the chosen relations in the relation table?

或多或少与上面的想法相同但更简单,因为您不需要与数据库中的原始状态进行比较:

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

关于c# - 如何使用 EF 在 MVC Code-first 中更新/创建多对多关系数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11385429/

相关文章:

c# - Fluentvalidation WithMessage 和单例实例

validation - MVC 3 Razor @Html.ValidationMessageFor 无法通过 jquery.load() 部分加载

c# - MVC Razor 隐藏输入和传递值

c# - 如何启用 nginx 反向代理以在 .Net 核心中与 gRPC 一起使用?

asp.net-mvc - 不使用身份的外部登录 asp.net core 2.0

c# - 如何使用 ExcelDNA 从范围中获取 Excel 公式?

jquery - 使用 jquery ajax 传递数据

asp.net-mvc - 使用 OutputCacheAttribute 时忽略 SetLastModified

c# - SMO "Restore failed for Server"从文件恢复备份

c# - AspNet.Security.OpenIdConnect.Server。刷新 token