Подтвердить что ты не робот

Entity Framework 4 Не сохраняйте строки "многие-ко-многим"

Надеюсь, очень простой вопрос. Но я использую 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; }
}

База данных была сгенерирована правильно и содержит таблицу ссылок, называемую CategoryServiceTypes. Моя проблема заключается в том, что я добавляю элементы в коллекцию ServiceTypes и сохраняю вызов и, хотя ошибки не происходит, никакие строки не добавляются в CategoryServiceTypes. Когда нижеприведенный код получает значение SaveChanges, количество по категориям. 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);
    }

Надеюсь, что я делаю что-то явно не так. Любые идеи?

Спасибо.

EDIT:

Хотя приведенный ниже ответ действительно правильный ответ, я думал, что добавлю следующую окончательную версию метода "Редактировать сообщение":

    [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 ничего не сделала.

4b9b3361

Ответ 1

Попробуйте переместить строку, в которую вы привязываете категорию к контексту перед циклом:

[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 не замечает, что вы добавили параметры servicetypes, потому что вы привязываете категорию к контексту, когда службы уже находятся в коллекции category.ServiceTypes, и все сервисы уже привязаны к контексту в состоянии Unchanged.