简体   繁体   中英

How to delete a foreign key record with Entity Framework?

I've got two models - Parent and Child. When I delete the Parent, I was hoping the Child would get deleted as it has a ForeignKey attribute however that's not the case. I could add logic within the Parent repository's Delete method as shown in the commented out code below but I was wondering if that's required of if there's a simpler way to go about this?

public record Parent
{
    [Key]
    public Guid Id { get; set; }
    public string Name { get; set; }
}

public record Child
{
    [Key]
    public Guid Id { get; set; }
    [ForeignKey("Parent")]
    public Guid ParentId { get; set; }
    public string Name { get; set;}
}

public void Delete(Guid id)
{
    /*
    var children = _dbContext.Childs.Where(c => c.ParentId == id);
    if (children != null)
    {
        foreach (var child in children)
        {
            _dbContext.Childs.Remove(child);
        }
    }
    */

    var parent = _dbContext.Parents.FirstOrDefault(p => p.Id == id);
    if (parent != null)
    {
        _dbContext.Parents.Remove(parent);
    }
    
    _dbContext.SaveChanges();
}

If the model in the databaseContext snapshot has ".OnDelete(DeleteBehavior.Cascade)" you could just include the table and the child data will be removed.

var parent = _dbContext.Parents.Include(parent => parent.Children).FirstOrDefault(p => p.Id == id);

For this to work you should also make a list of Children in the parent model:

public record Parent
{
    [Key]
    public Guid Id { get; set; }
    public string Name { get; set; }

    public IEnumerable<Child> Children { get; set; }
}

This is the link to the Microsoft documentation

Include the Child when querying the parent as the following:

    var parent = _dbContext.Parents
        .include(p => p.Child)
        .FirstOrDefault(p => p.Id == id);

Then call remove as you already doing.

Also, you may want to consider the OnDelete behavior to define what happens to Child when you delete the Parent. If you want the Child to be deleted when the parent is deleted use "Cascade" delete behavior. This can be done at database level in Child table definition similar to the following:

CONSTRAINT [FK_Childs_Parents_ParentId] FOREIGN KEY ([ParentId]) REFERENCES [Parent]  ON DELETE CASCADE 

or at EF context level as the following:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<Parent>()
        .HasMany(e => e.Childs)
        .WithOne(e => e.Parent)
        .OnDelete(DeleteBehavior.ClientCascade);
}

Further related details from official Microsoft documentation here

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