web-dev-qa-db-ja.com

1対0または1対1の関係のEntity Framework(EF)Code First Cascade Delete

Pluralsight「Entity Framework 5入門」コース、Julie Lerman の「Code First Modeling」セクションに続いて、one-toで2つのPOCOクラスを作成しました-zero-or-one関係:親(ユーザー)とoptional子(UserDetail)。

ser and UserDetailデータモデル図(クリックして表示)

図では、UserIdプロパティがUserDetailの主キーおよび外部キーであることに注意してください。

関連コード:

public class User
{
    //...

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }

    /* Has a 1:0..1 relationship with UserDetail */
    public virtual UserDetail UserDetail { get; set; }

    //...
}

public class UserDetail
{
    //...

    /* Has a 0..1:1 relationship with User */
    public virtual User User { get; set; }

    [Key, ForeignKey("User")]
    public int UserId { get; set; }

    //...
}

public class EFDbContext : DbContext
{
    public DbSet<User> Users { get; set; }
    //public DbSet<UserDetail> UserDetails { get; set; }  /* Explicit declaration not necessary. Context is aware of UserDetail entity due to 0..1:1 relationship with User */

    public EFDbContext()
    {
        Configuration.ProxyCreationEnabled = true;
        Configuration.LazyLoadingEnabled = true;
    }
}

public class UserRepository : IUserRepository
{
    private EFDbContext _context = new EFDbContext();

    public void Delete(User entity)
    {
        entity = _context.Users.Find(entity.UserId);

        //...

        _context.Users.Remove(entity);
        _context.SaveChanges();

        //...
    }
}

UserRepositoryクラスのDelete()メソッドが呼び出されると、UserDetailの外部キーでカスケード削除が有効になっていないため、データベースのUserレコードは削除されません。

DELETEステートメントは、REFERENCE制約「FK_dbo.UserDetail_dbo.User_UserId」と競合しました。

Entity Framework Code Firstを使用して1対0または1つの関係のカスケード削除をどのように有効にしますか(ユーザーを削除するとUserDetailが自動的に削除されます) ?

51
arsenalogy

これを行うには、流れるようなAPIを使用する必要があります。

以下をDbContextに追加してみてください:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{   
    modelBuilder.Entity<User>()
        .HasOptional(a => a.UserDetail)
        .WithOptionalDependent()
        .WillCascadeOnDelete(true);
}
71
hutchonoid

これを行うことにより、アプリケーションのグローバルスコープでカスケード削除規則を無効にすることもできます。

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>()
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>()
3
rajeemcariazo

このコードは私のために働いた

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<UserDetail>()
            .HasRequired(d => d.User)
            .WithOptional(u => u.UserDetail)
            .WillCascadeOnDelete(true);
    }

移行コードは次のとおりです。

public override void Up()
    {
        AddForeignKey("UserDetail", "UserId", "User", "UserId", cascadeDelete: true);
    }

そして、それはうまくいきました。初めて使用したとき

modelBuilder.Entity<User>()
    .HasOptional(a => a.UserDetail)
    .WithOptionalDependent()
    .WillCascadeOnDelete(true);

移行コードは次のとおりです。

AddForeignKey("User", "UserDetail_UserId", "UserDetail", "UserId", cascadeDelete: true); 

ただし、使用可能な2つのオーバーロードのいずれにも一致しません(EntityFramework 6)

1
Lupa