Entity framework не сохраняет свойство объекта

Я разрабатываю интернет-магазин, используя платформу ASP.Net MVC 4.

У меня есть объект Category — категория товаров в магазине (мужская одежда — например):

public class Category
{
    [Required]
    public long id { get; set; }

    [Required]
    public string name { get; set; }

    public bool active { get; set; }
    public bool displayOnTop { get; set; }
    public bool showSubcategoriesItems { get; set; }

    public Category parentCategory { get; set; }

    public virtual Collection<Item> items { get; set; }

    public Category()
    {
        this.items = new Collection<Item>();
    }
}

Есть свойство parentCategory — оно означает, что эта категория входит в другую (например, Мужская одежда > Рубашки).

Для редактирования существующей категории I используйте следующее действие:

[HttpPost]
public ActionResult EditCategory(Category editedCategory, string parentCategorySelector)
{
    UsersContext db = new UsersContext();

    Category existingCategory = db.categories.SingleOrDefault(c => c.id == editedCategory.id);
    long parentCategoryId = (long)Int32.Parse(parentCategorySelector);
    Category parentCategory = db.categories.SingleOrDefault(c => c.id == parentCategoryId);

    if (existingCategory == null) return RedirectToAction("Index", "Admin");

    existingCategory.name = editedCategory.name;
    existingCategory.active = editedCategory.active;
    existingCategory.displayOnTop = editedCategory.displayOnTop;
    existingCategory.showSubcategoriesItems = editedCategory.showSubcategoriesItems;
    existingCategory.parentCategory = parentCategory;

    db.Entry(existingCategory.parentCategory).State = EntityState.Modified;
    db.SaveChanges();

    return View(existingCategory);
}

Все работает нормально, за исключением случаев, когда я хочу установить для parentCategory значение null — оно устанавливается в значение null в коде, но значение null не сохраняется в базе данных — предыдущее значение все еще существует.

Но если я сделаю это так:

[HttpPost]
public ActionResult EditCategory(Category editedCategory, string parentCategorySelector)
{
    UsersContext db = new UsersContext();

    Category existingCategory = db.categories.SingleOrDefault(c => c.id == editedCategory.id);
    long parentCategoryId = (long)Int32.Parse(parentCategorySelector);
    Category parentCategory = db.categories.SingleOrDefault(c => c.id == parentCategoryId);

    if (existingCategory == null) return RedirectToAction("Index", "Admin");

    existingCategory.name = editedCategory.name;
    existingCategory.active = editedCategory.active;
    existingCategory.displayOnTop = editedCategory.displayOnTop;
    existingCategory.showSubcategoriesItems = editedCategory.showSubcategoriesItems;
    existingCategory.parentCategory = null;

    db.Entry(existingCategory.parentCategory).State = EntityState.Modified;
    db.SaveChanges();

    return View(existingCategory);
}

т.е. я установил его в ноль без условий, он сохраняется правильно.

Что я делаю не так?


person Eugene Rozhkov    schedule 13.07.2015    source источник


Ответы (1)


Почему нет атрибута Key в разделе Category.id? Если id является первичным ключом, он должен быть там.

Вы должны использовать Включить для загрузки связанных объектов :

   [HttpPost]
    public ActionResult EditCategory(Category editedCategory, string parentCategorySelector)
    {
        using(UsersContext db = new UsersContext())
        {
            Category existingCategory = db.categories.Include(c => c.parentCategory).SingleOrDefault(c => c.id == editedCategory.id);
            long parentCategoryId = (long)Int32.Parse(parentCategorySelector);
            Category parentCategory = db.categories.SingleOrDefault(c => c.id == parentCategoryId);

            if (existingCategory == null) return RedirectToAction("Index", "Admin");

            existingCategory.name = editedCategory.name;
            existingCategory.active = editedCategory.active;
            existingCategory.displayOnTop = editedCategory.displayOnTop;
            existingCategory.showSubcategoriesItems = editedCategory.showSubcategoriesItems;
            existingCategory.parentCategory = parentCategory;

            db.SaveChanges();

            return View(existingCategory);
        }
    }

Обратите внимание, как правильно расположен DbContext.

person mt_serg    schedule 13.07.2015
comment
Большое спасибо - это работает для меня! Действительно, инструкция Include принимает строку вместо лямбда: Include(parentCategory) - person Eugene Rozhkov; 13.07.2015
comment
рад помочь! Включение, которое принимает лямбда, находится в System.Data.Entity, начиная с EF 4.1. - person mt_serg; 14.07.2015