简体   繁体   中英

Entity Framework Core, deleting items from nested collection

I have two classes

 public class InvoiceRow
    {
        public int Id { get; set; }
        public int InvoiceId { get; set; }

        public int ProductId { get; set; }
        public virtual Product Product { get; set; }

        public int Amount { get; set; }
    }



   public class Invoice
    {
            public int Id { get; set; }
            private ICollection<InvoiceRow> _rows;
            public virtual ICollection<InvoiceRow> Rows => _rows ?? (_rows = new List<InvoiceRow>());
    }

I use Update method in the repository class

  public void Update(Invoice record)
  {
            dB.Invoices.Update(record);
            dB.SaveChanges();
  }

It works for updating values in the collection of rows and adding new rows as well, however it doesn't remove items, if I pass object with less rows than it has in the database. What is the best approach to do it?

That is because the rows in the database are not marked for deletion.

Only new or changed items are updated. 'Missing' items from a collection are not considered to be deleted.

So what you'll need to do is mark the items for deletion yourself. Something like this:

public void Update(Invoice record)
{
    var missingRows = dB.InvoiceRows.Where(i => i.InvoiceId == record.Id)
                        .Except(record.Rows);
    dB.InvoiceRows.RemoveRange(missingRows);

    dB.Invoices.Update(record);
    dB.SaveChanges();
}

Another solution would be to declare a composite primary key InvoiceRow.Id and InvoiceRow.InvoiceId . Now it is an Identifying Relationship . As such, EF Core will indeed delete the child records when they are removed from the parent.

https://stackoverflow.com/a/17726414/7718171

https://stackoverflow.com/a/762994/7718171

remove-from-collection-does-not-mark-object-as-deleted

I'm using Entity Framework Core 6 and the following code works for me.

public void Update(Invoice invoice)
{

        //1. valid invoice rows ids
        var validInvoiceRowIds = invoice.InvoiceRows.Select(ir => ir.Id).ToList();

        //2. missing invoice rows
        var missItems = _context.InvoiceRows
            .Where(ir => ir.InvoiceId == invoice.Id && !validInvoiceRowIds.Contains(ir.Id))
            .ToList();

        _context.RemoveRange(missItems);

        _context.Update(entity);
        _context.SaveChanges();

}

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