31

EntityFramework のドキュメントには、次の動作が可能であると記載されています。

依存エンティティの外部キーが null 許容の場合、Code First はリレーションシップにカスケード削除を設定せず、プリンシパルが削除されると、外部キーは null に設定されます。

( http://msdn.microsoft.com/en-us/jj591620から)

しかし、私はそのような行動を達成することはできません。

コードファーストで定義された次のエンティティがあります。

public class TestMaster
{
    public int Id { get; set; }
    public string Name { get; set; }        
    public virtual ICollection<TestChild> Children { get; set; }       
}

public class TestChild
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual TestMaster Master { get; set; }
    public int? MasterId { get; set; }
}

Fluent API マッピング構成は次のとおりです。

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<TestMaster>()
                    .HasMany(e => e.Children)
                    .WithOptional(p => p.Master).WillCascadeOnDelete(false);

        modelBuilder.Entity<TestChild>()
                    .HasOptional(e => e.Master)
                    .WithMany(e => e.Children)
                    .HasForeignKey(e => e.MasterId).WillCascadeOnDelete(false);
    }

外部キーは null 可能で、ナビゲーション プロパティはオプションとしてマップされるため、カスケード削除が MSDN の説明どおりに機能することを期待しています。つまり、すべての子の MasterID を無効にしてから、Master オブジェクトを削除します。

しかし、実際に削除しようとすると、FK 違反エラーが発生します。

 using (var dbContext = new TestContext())
        {
            var master = dbContext.Set<TestMaster>().Find(1);
            dbContext.Set<TestMaster>().Remove(master);
            dbContext.SaveChanges();
        }

SaveChanges() では、次がスローされます。

System.Data.Entity.Infrastructure.DbUpdateException : An error occurred while updating the entries. See the inner exception for details.
----> System.Data.UpdateException : An error occurred while updating the entries. See the inner exception for details.
----> System.Data.SqlClient.SqlException : The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.TestChilds_dbo.TestMasters_MasterId". The conflict occurred in database "SCM_Test", table "dbo.TestChilds", column 'MasterId'.
The statement has been terminated.

私は何か間違ったことをしていますか、それとも MSDN の内容を誤解していましたか?

4

2 に答える 2

44

説明どおりに機能しますが、MSDNの記事では、親エンティティだけでなく、子もコンテキストにロードされている場合にのみ機能することを強調していません。Findしたがって、 (親のみをロードする)を使用する代わりに、Include(または子をコンテキストにロードする他の方法で)熱心なロードを使用する必要があります。

using (var dbContext = new TestContext())
{
    var master = dbContext.Set<TestMaster>().Include(m => m.Children)
        .SingleOrDefault(m => m.Id == 1);
    dbContext.Set<TestMaster>().Remove(master);
    dbContext.SaveChanges();
}

これにより、マスターがデータベースから削除され、Childエンティティ内のすべての外部キーがに設定さnullれ、子のUPDATEステートメントがデータベースに書き込まれます。

于 2013-03-05T17:48:34.947 に答える