2016-08-16 12 views
1

私は以下のオブジェクトをEFで定義しています。Entity Frameworkの子レコードの特定と削除

public class ItemA() 
{ 
     public virtual ICollection<ItemB> Items{ get; set; } 
} 

public class ItemB() 
{ 
     public virtual ICollection<ItemC> Items{ get; set; } 
} 

私のコードでは、次のことを行っています。 ItemAのインスタンスが移入され

myItemA.Items.Remove(myItemA.Items.FirstOrDefault(x => (int)x.Type == model.Type)); 

myItemA.Items.Add(new ItemB()); 

は、それが単一ItemBが含まれていると私は単純にItemBの新しいインスタンスでこれを置き換えたいです。メッセージを更新するために私のサービスに入ると、次のコードを呼び出すだけで新しいItemBが作成され、既存のItemBは親IDがnullの孤立した状態になります。 ItemBとItemC間のリンクはそのままです。

_dbContext.Entry(entity).State = EntityState.Modified; 
_dbContext.SaveChanges(); 

だから、私は私がモデルで削除するItemB子と制約のセットアップがうまくいけば、カスケード子ItemCレコード、その後、孤立ItemBを削除することEFを伝える必要があることを知っています。しかし、私はそうする方法を見つけるのに苦労しています。

親アイテムをコンテクストから再取得してリストを比較し、それらを削除済みとしてマークしようとしましたが、プロキシを戻しているので、両方のオブジェクトは基本的に同じで、更新されたItemBのみを持ちます。元の。

var existingItem = GetItem(entity.Id); 

または

var existing Items = GetItem(entity.Id).Items.ToList(); 

だから私は必要なもの、オリジナルItemA.Itemsは、彼らが削除されるEFを伝えることができるようにすることです。 EFに何かを削除するよう指示する方法はわかっていますが、削除する必要があるエンティティへの参照を取得することにのみ関心があります。このコードを追加する

EDIT

はそれが仕事になり、(子ItemC付き)孤立ItemBが削除されるようになりました、しかし、私の知る限りそれを理解するように、これは今、2つのトランザクション内で実行されます。

//Update Message 
    _dbContext.Entry(entity).State = EntityState.Modified; 
    _dbContext.SaveChanges(); 

    //Remove any orphaned records 
    var itemsToRemove = _dbContext.Set<ItemB>().Where(x => x.ItemA == null).ToList(); 
    _dbContext.Set<ItemB>().RemoveRange(itemsToRemove); 
    _dbContext.SaveChanges(); 

理想的には、この単一SaveChanges()

+0

エンティティの状態を削除しようとしましたか? 'foreach(item.Itemsのvar子アイテム)dbContext.Entry(childItem).State = EntityState.Deleted;'? –

+0

これは問題です。item.Itemsには削除したい項目が含まれていません。新しい項目Bのみが追加され、元のItemBは孤立したままになります。 – ChrisBint

+0

削除して再追加する前のことを意味します。しかし、あなたは次の行で削除しようとしていますか? 'item.Items.Remove(item.Items.FirstOrDefault(x =>(int)x.Type == model.Type));'どこでアイテムを取得しますか?データベースから? –

答えて

0

ウムを行うための方法を探して..私は何か間違ったことを理解したのか、あなただけのカスケードは次のように削除を実装したいです:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<ItemB>().HasRequired(b => b.Parent).WithMany(a => a.Items).WillCascadeOnDelete(); 
} 

これも動作するはずです:

public class ItemA() 
{ 
    public virtual ICollection<ItemB> Items{ get; set; } 
} 

public class ItemB() 
{ 
    [Required] // This set's the constraint 
    public virtual ItemA Parent { get; set; } 
    public virtual ICollection<ItemC> Items{ get; set; } 
} 

もう1つは使用しませんでしたが、同じ結果をもたらす。

関連する問題