asp.net-mvc - Entity Framework 4 不保存我的多对多行

标签 asp.net-mvc entity-framework many-to-many ef-code-first

希望这是一个非常简单的问题。但我在 MVC 应用程序中使用 Code First,并且有一个具有多对多关系的 Category 和 ServiceType 对象:

public class Category
{
    public Category()
    {
        ServiceTypes = new HashSet<ServiceType>();
    }

    public Guid CategoryId { get; set; }

    [Required(ErrorMessage = "Name is required")]
    public string Name { get; set; }

    public virtual ICollection<ServiceType> ServiceTypes { get; set; }
}

数据库已正确生成,并包含一个名为 CategoryServiceTypes 的链接表。我的问题是,我将项目添加到 ServiceTypes 集合并调用 save,尽管没有发生错误,但没有向 CategoryServiceTypes 添加任何行。当下面的代码到达 SaveChanges 时,category.ServiceTypes 的计数为 1,因此集合中肯定有某些内容:

    [HttpPost]
    public ActionResult Edit(Category category, Guid[] serviceTypeIds)
    {
        if (ModelState.IsValid)
        {
            // Clear existing ServiceTypes
            category.ServiceTypes.Clear();

            // Add checked ServiceTypes
            foreach (Guid serviceType in serviceTypeIds)
            {
                ServiceType st = db.ServiceTypes.Find(serviceType);
                category.ServiceTypes.Add(st);
            }

            db.Entry(category).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(category);
    }

我希望我在这里做了一些明显错误的事情。有什么想法吗?

谢谢。

编辑:

虽然下面的响应确实是正确的答案,但我想我应该添加以下最终版本的编辑帖子方法:

    [HttpPost]
    public ActionResult Edit(Category category, Guid[] serviceTypeIds)
    {
        if (ModelState.IsValid)
        {
            // Must set to modified or adding child records does not set to modified
            db.Entry(category).State = EntityState.Modified;

            // Force loading of ServiceTypes collection due to lazy loading
            db.Entry(category).Collection(st => st.ServiceTypes).Load(); 

            // Clear existing ServiceTypes
            category.ServiceTypes.Clear();

            // Set checked ServiceTypes
            if (serviceTypeIds != null)
            {
                foreach (Guid serviceType in serviceTypeIds)
                {
                    ServiceType st = db.ServiceTypes.Find(serviceType);
                    category.ServiceTypes.Add(st);
                }
            }

            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(category);
    }

请注意强制加载 ServiceTypes 集合的行,这是必需的,因为延迟加载不包括这些子项,这意味着清除 ServiceTypes 集合不会执行任何操作。

最佳答案

尝试将类别附加到循环前面的上下文的行移动:

[HttpPost]
public ActionResult Edit(Category category, Guid[] serviceTypeIds)
{
    if (ModelState.IsValid)
    {
        // Clear existing ServiceTypes
        category.ServiceTypes.Clear();
        db.Entry(category).State = EntityState.Modified;
        // category attached now, state Modified

        // Add checked ServiceTypes
        foreach (Guid serviceType in serviceTypeIds)
        {
            ServiceType st = db.ServiceTypes.Find(serviceType);
            // st attached now, state Unchanged
            category.ServiceTypes.Add(st);
            // EF will detect this as a change of category and create SQL
            // to add rows to the link table when you call SaveChanges
        }

        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(category);
}

在您的代码中,EF 不会注意到您已添加服务类型,因为当服务类型已位于 category.ServiceTypes 集合中并且所有服务类型已附加到时,您将类别附加到上下文上下文处于状态未更改

关于asp.net-mvc - Entity Framework 4 不保存我的多对多行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9520111/

相关文章:

Android Room Many to Many Junction 表获得超过 2 个表的关系

java - 多对多关系更新?

c# - Automapper - 将多对多关联映射到平面对象的最佳实践

asp.net - 如何为 Web API GET 请求指定用户名和密码

asp.net - 我是否应该对映射表使用复合键,该复合键也用于外键?

c# - 对 EF-to-Linq 查询进行排序的最快方法是什么?

c# - OData 错误 : The query specified in the URI is not valid. 该属性不能在查询选项中使用

c# - MVC4 和路由

json - IIS 8 阻止 JSON 有效负载字段的请求

asp.net-mvc - ApiController 按原样返回 JSON 字符串