У меня есть модель Business
и Category
.
Каждый Business
имеет множество Categories
через открытую коллекцию (Category
игнорирует объект Business
).
Теперь вот мой контроллер-действие:
[HttpPost]
[ValidateAntiForgeryToken]
private ActionResult Save(Business business)
{
//Context is a lazy-loaded property that returns a reference to the DbContext
//It disposal is taken care of at the controller Dispose override.
foreach (var category in business.Categories)
Context.Categories.Attach(category);
if (business.BusinessId > 0)
Context.Businesses.Attach(business);
else
Context.Businesses.Add(business);
Context.SaveChanges();
return RedirectToAction("Index");
}
Теперь существует несколько business.Categories
, у которых их CategoryId
установлено в существующее Category
(свойство Title
Category
отсутствует).
После нажатия SaveChanges
и перезагрузки Business
с сервера Categories
не существует.
Итак, мой вопрос в том, как правильно установить business.Categories
с заданным массивом существующих CategoryId
s.
Однако при создании нового Business
при вызове SaveChanges
:
DbUpdateException
Произошла ошибка при сохранении объектов, которые не отображают свойства внешнего ключа для своих отношений. Свойство EntityEntries вернет значение null, потому что один объект не может быть идентифицирован как источник исключения. Обработка исключений при сохранении может быть упрощена путем отображения свойств внешнего ключа в ваших типах объектов. Подробнее см. В InnerException.
Внутреннее исключение (OptimisticConcurrencyException
):
Заявление об обновлении, вставке или удалении повлияло на неожиданное количество строк (0). Объекты могут быть изменены или удалены, поскольку объекты загружены. Обновить записи ObjectStateManager.
Update
после ответа, здесь код обновления:
var storeBusiness = IncludeChildren().SingleOrDefault(b => b.BusinessId == business.BusinessId);
var entry = Context.Entry(storeBusiness);
entry.CurrentValues.SetValues(business);
//storeBusiness.Categories.Clear();
foreach (var category in business.Categories)
{
Context.Categories.Attach(category);
storeBusiness.Categories.Add(category);
}
При вызове SaveChanges
я получаю следующее DbUpdateException
:
Произошла ошибка при сохранении объектов, которые не отображают свойства внешнего ключа для своих отношений. Свойство EntityEntries вернет значение null, потому что один объект не может быть идентифицирован как источник исключения. Обработка исключений при сохранении может быть упрощена путем отображения свойств внешнего ключа в ваших типах объектов. Подробнее см. В InnerException.
Вот как выглядят модели Business/Category:
public class Business
{
public int BusinessId { get; set; }
[Required]
[StringLength(64)]
[Display(Name = "Company name")]
public string CompanyName { get; set; }
public virtual BusinessType BusinessType { get; set; }
private ICollection<Category> _Categories;
public virtual ICollection<Category> Categories
{
get
{
return _Categories ?? (_Categories = new HashSet<Category>());
}
set
{
_Categories = value;
}
}
private ICollection<Branch> _Branches;
public virtual ICollection<Branch> Branches
{
get
{
return _Branches ?? (_Branches = new HashSet<Branch>());
}
set
{
_Branches = value;
}
}
}
public class Category
{
[Key]
public int CategoryId { get; set; }
[Unique]
[Required]
[MaxLength(32)]
public string Title { get; set; }
public string Description { get; set; }
public int? ParentCategoryId { get; set; }
[Display(Name = "Parent category")]
[ForeignKey("ParentCategoryId")]
public virtual Category Parent { get; set; }
private ICollection<Category> _Children;
public virtual ICollection<Category> Children
{
get
{
return _Children ?? (_Children = new HashSet<Category>());
}
set
{
_Children = value;
}
}
}
Просто, чтобы снова очистить, Category
я прикрепляюсь к существующим/новым Business
es уже существует в БД и имеет идентификатор, который я использую для присоединения к нему.