私は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's disposal is taken care of at the controller's 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
ただし、新しいものを作成するDbUpdateException
と、呼び出し時に次の例外がスローされますSaveChanges
。
リレーションシップの外部キー プロパティを公開しないエンティティの保存中にエラーが発生しました。単一のエンティティを例外のソースとして識別できないため、EntityEntries プロパティは null を返します。保存中の例外の処理は、エンティティ タイプで外部キー プロパティを公開することで簡単に行うことができます。詳細については、InnerException を参照してください。
内部例外 ( OptimisticConcurrencyException
):
Store update、insert、または delete ステートメントが予期しない数の行 (0) に影響を与えました。エンティティが読み込まれてから、エンティティが変更または削除された可能性があります。ObjectStateManager エントリを更新します。
アップデート
回答後、更新コードは次のとおりです。
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 を参照してください。
ビジネス/カテゴリ モデルは次のようになります。
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 は既に DB に存在し、アタッチに使用している ID を持っています。