实体框架4不保存我的多对多行

Gar*_*ary 12 asp.net-mvc many-to-many entity-framework ef-code-first

希望是一个非常简单的问题.但我正在使用Code First和MVC应用程序,并且我有一个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; }
}
Run Code Online (Sandbox Code Playgroud)

数据库已正确生成,并包含一个名为CategoryServiceTypes的链接表.我的问题是我将项目添加到我的ServiceTypes集合并调用保存,虽然没有发生错误,但没有行添加到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);
    }
Run Code Online (Sandbox Code Playgroud)

我希望我在这里做一些明显错误的事情.有任何想法吗?

谢谢.

编辑:

虽然下面的回答确实是正确答案,但我认为我会添加以下最终版本的Edit post方法:

    [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);
    }
Run Code Online (Sandbox Code Playgroud)

注意强制加载ServiceTypes集合的行,这是必需的,因为延迟加载不包括那些子项,这意味着清除ServiceTypes集合什么都不做.

Sla*_*uma 8

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

[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);
}
Run Code Online (Sandbox Code Playgroud)

在您的代码中,EF没有注意到您添加了servicetypes,因为当servicetypes已经在category.ServiceTypes集合中并且所有servicetypes已经附加到状态中的上下文时,您将类别附加到上下文Unchanged.