EntityFramework和级联删除

本文关键字:删除 级联 EntityFramework | 更新日期: 2023-09-27 18:03:09

我有一个级联删除的问题。如果可能的话,我想使用它,但在某些情况下,它不适合我。我已经设置了我的DbContext看起来像这样:

public class DatabaseContext : IdentityDbContext<User>
{
    // Define our tables
    public DbSet<Company> Companies { get; set; }
    public DbSet<Center> Centers { get; set; }
    public DbSet<Collection> Collections { get; set; }
    public DbSet<UserCenter> UserCenters { get; set; }
    public DbSet<Journal> Journal { get; set; }
    /// <summary>
    /// static constructor (only gets called once)
    /// </summary>
    static DatabaseContext()
    {
        // Create the database and insert our records
        Database.SetInitializer<DatabaseContext>(new DatabaseInitializer());
    }
    /// <summary>
    /// Default constructor
    /// </summary>
    public DatabaseContext()
        : base("DefaultConnection")
    {
        // Write our SQL to the debug window
        this.Database.Log = s => Debug.WriteLine(s);
        // Disable Lazy Loading
        base.Configuration.LazyLoadingEnabled = false;
    }
    // Public static method for OWIN
    public static DatabaseContext Create()
    {
        return new DatabaseContext();
    }
    /// <summary>
    /// Overrides the inherited OnModelCreated method.
    /// </summary>
    /// <param name="modelBuilder">The DbModelBuilder</param>
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Change default table names for Identity Framework
        modelBuilder.Entity<IdentityRole>().ToTable("Roles");
        modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles");
        modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims");
        modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogins");
        // Create mappings for Identity Framework
        modelBuilder.Entity<IdentityUserLogin>().HasKey(m => new { m.UserId, m.ProviderKey });
        modelBuilder.Entity<IdentityRole>().HasKey<string>(m => m.Id);
        modelBuilder.Entity<IdentityUserRole>().HasKey(m => new { m.RoleId, m.UserId });
        modelBuilder.Entity<User>().HasMany(m => m.Logins).WithRequired().HasForeignKey(m => m.UserId);
        modelBuilder.Entity<IdentityRole>().HasMany(m => m.Users).WithRequired().HasForeignKey(m => m.RoleId);
        // Create our mappings
        modelBuilder.Entity<UserCenter>().HasKey(m => new { m.UserId, m.CenterId });
        modelBuilder.Entity<Center>().HasRequired(m => m.Company).WithMany(m => m.Centers).HasForeignKey(m => m.CompanyId);
        modelBuilder.Entity<Center>().HasMany(m => m.Collections).WithRequired().HasForeignKey(m => m.CenterId);
        modelBuilder.Entity<Company>().HasMany(m => m.Members).WithOptional().HasForeignKey(m => m.CompanyId).WillCascadeOnDelete(false);
        // Archive relationships
        modelBuilder.Entity<User>().HasOptional(m => m.CreatedBy).WithMany().HasForeignKey(m => m.CreatedById).WillCascadeOnDelete(false);
        modelBuilder.Entity<User>().HasOptional(m => m.ModifiedBy).WithMany().HasForeignKey(m => m.ModifiedById).WillCascadeOnDelete(false);
        modelBuilder.Entity<Company>().HasRequired(m => m.CreatedBy).WithMany().HasForeignKey(m => m.CreatedById).WillCascadeOnDelete(false);
        modelBuilder.Entity<Company>().HasRequired(m => m.ModifiedBy).WithMany().HasForeignKey(m => m.ModifiedById).WillCascadeOnDelete(false);
        modelBuilder.Entity<Collection>().HasRequired(m => m.CreatedBy).WithMany().HasForeignKey(m => m.CreatedById).WillCascadeOnDelete(false);
        modelBuilder.Entity<Collection>().HasRequired(m => m.ModifiedBy).WithMany().HasForeignKey(m => m.ModifiedById).WillCascadeOnDelete(false);
        modelBuilder.Entity<Center>().HasRequired(m => m.CreatedBy).WithMany().HasForeignKey(m => m.CreatedById).WillCascadeOnDelete(false);
        modelBuilder.Entity<Center>().HasRequired(m => m.ModifiedBy).WithMany().HasForeignKey(m => m.ModifiedById).WillCascadeOnDelete(false);
        modelBuilder.Entity<Journal>().HasRequired(m => m.User).WithMany().HasForeignKey(m => m.UserId).WillCascadeOnDelete(false);
    }
}

如您所见,我有一些存档映射,在删除时禁用了Cascade。这是设计的,因为我不想删除一个项目,它删除了创建/修改它的用户:)

如果我删除一个Center并且它有一些Collections,它会删除,集合被删除。同样的,如果我删除一个用户,他有一些UserCenters两者都将被删除,但如果我试图删除一个公司(其中有用户和用户有UserCenters)它失败了,我得到一个异常:

exceptionMessage= DELETE语句与REFERENCE约束" fk_dbo . users_dbo . companyies_companyid "冲突。冲突发生在数据库"melanite",表"dbo"中。"Users",列"CompanyId"。语句已被终止。

我可以看到它在UserCompanyId字段呻吟,所以我更改了这一行:

modelBuilder.Entity<Company>().HasMany(m => m.Members).WithOptional().HasForeignKey(m => m.CompanyId).WillCascadeOnDelete(false);

因为如果我删除User,我不希望它删除User所属的Company。但是,另一方面,如果我删除Company,我确实希望它删除Users…

有人知道我怎么能解决我的问题吗?

EntityFramework和级联删除

只需将FK配置为在级联上删除:

modelBuilder.Entity<Company>().HasMany(m => m.Members).WithOptional().HasForeignKey(m => m.CompanyId).WillCascadeOnDelete(true);

级联删除总是在一个方向上工作,从引用表(Companies)到引用表(Users),所以删除公司也会删除它的用户,但是删除用户不会对引用公司做任何事情。