简体   繁体   中英

Cascade delete on classes inherited from ApplicationUser(IdentityUser)

I have two classes that are inherited from ApplicationUser in ASP .NET Identity, classes are as follows :

This is my ApplicationUser class

public class ApplicationUser : IdentityUser
{
    public string Name { get; set; }

    public string Surname { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }
}

And two classes that inherited it :

public class User : ApplicationUser
{
    public virtual ICollection<Repair> Repairs { get; set; }

    public virtual ICollection<Vehicle> Vehicles { get; set; }
}

public class Repairer : ApplicationUser
{
    public virtual ICollection<Repair> Repairs { get; set; }
}

When I run Code First migrations both classes are inside the same table which is AspNetUsers table with proper Discriminator and role. The problem is that when I remove some User from system I also want all vehicles and repair to be removed from my database but since in plain database there is no proper distinction beside discriminator of which user it is I didn't find a way to set cascade delete on foreign key constraints that reference proper tables in database (Vehicle and Repair) so instead either I got an exception or my foreign key in db is set to null.

Is it a way to achieve cascade delete or should I change my model because from other than this everything is working fine.

Thanks in advance!

Trying to solve a similar problem and wound up here, so I'll contribute what I've learned so far. In my case I have a base ApplicationUser with two inheriting classes containing specific (entity) properties:

public class ApplicationUser : IdentityUser {

} 

public class Server : ApplicationUser {

}

public class HumanUser : ApplicationUser {

    [Required]
    public virtual GlobalInventory GlobalInventory { get; set; }
}

public class GlobalInventory {

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

    [Required]
    public virtual HumanUser User { get; set; }
}

I've also added the following Fluid API code to ApplicationDbContext:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<HumanUser>().HasOptional(x => x.GlobalInventory).WithRequired(x => x.User).WillCascadeOnDelete(true);
        base.OnModelCreating(modelBuilder);
    }

Here's the migration part that Code First chucks out for GlobalInventory. Notice that the foreign key connection to HumanUser is without the "cascadeDelete: true" flag. That means that when I delete the parent, errors will occur:

        CreateTable(
            "dbo.GlobalInventories",
            c => new
                {
                    UserId = c.String(nullable: false, maxLength: 128),
                })
            .PrimaryKey(t => t.UserId)
            .ForeignKey("dbo.Users", t => t.UserId)
            .Index(t => t.UserId);

BUT - if I make GlobalInventory a property of the base ApplicationUser class instead , like so:

public class ApplicationUser : IdentityUser {

    [Required]
    public virtual GlobalInventory GlobalInventory { get; set; }
} 

public class HumanUser : ApplicationUser {

    [Required]
    public virtual GlobalInventory GlobalInventory { get; set; }
}


public class GlobalInventory {

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

    [Required]
    public virtual ApplicationUser User { get; set; }
}

.. and modify the model building accordingly:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ApplicationUser>().HasOptional(x => x.GlobalInventory).WithRequired(x => x.User).WillCascadeOnDelete(true);
        base.OnModelCreating(modelBuilder);
    }

Then the migration code for GlobalInventory looks right, and I can delete Users knowing that the GlobalInventory will be removed also:

        CreateTable(
            "dbo.GlobalInventories",
            c => new
                {
                    UserId = c.String(nullable: false, maxLength: 128),
                })
            .PrimaryKey(t => t.UserId)
            .ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
            .Index(t => t.UserId);

(This also works fine when ApplicationUser is defines as an abstract class)

I don't want to attach specific entity properties to the base class though, so this is where I'm currently stuck at. It's as if the Fluid API cascade-on-delete designation gets ignored, when applied to my inheriting classes, but not when applied to the base class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM