简体   繁体   中英

Deleting child items with EF Core

I have looked at several similar questions on deleting items from child collections in EF Core, and most do not have an accepted or answer relevant for EF Core:

https://stackoverflow.com/a/51349007 https://stackoverflow.com/a/49679247

I have a class called "Albums" and a property on it called "Musicians".

When I load Albums from the database with EF, I include the Musicians property so that the collection is already tracked by EF. If I add an item to the Musicians list and save changes on the Album entity, I notice it is added to the junction table for Musicians and Albums, and this works great. For deletes, this does not seem to have an effect.

Example:

var albums = repository.LoadAlbumsWithMusicians();
var musicians = CreateNewMusiciansForAlbumOne();

var test = albums.First().Musicians;
test.Clear();    
test.AddRange(musicians); 

With this code, if a composite primary key ( MusicianId , MusicianType , and AlbumId ) for a musician matches one which EF already knows about, even if it is actually a different object, it will do nothing as it knows this relationship already exists. That's what I expect.

If the primary key does not match an existing one then it will be treated as a new object in the collection and a new row is added to the database. That's also what I expect.

However, I can't seem to do anything that will make EF recognize that the items which were previously in the collection [and have been removed] should be deleted. In EF6, I simply used .Clear() and .AddRange() to handle these relationships, and EF handled the inserts and deletes for child relationships. Without explicitly removing these objects from the context as in this suggested answer, https://stackoverflow.com/a/49679247 , how can I ensure these deleted child items are removed from the database?

Using the example below lets say our "selectedAppender" contains a record by ID and all junction table data. In order to add items and remove items from that junction table all we need to do is account for them in a separate object (delete and add object).

Once we have a list of items to delete it's as simple as calling the "remove" method.

Let me know if this isn't clear enough. Hopefully it helps.

file_appender selectedAppender = context.file_appender.Find(dto.Id);

int[] ids = dto.Loggers.Where(x => !x.Selected).Select(x => x.Id).ToArray();
var loggers_to_delete = selectedAppender.logger.Where(x => ids.Contains(x.id));
loggers_to_delete.ToList().ForEach(x =>
{
    selectedAppender.logger.Remove(x);
});

ids = dto.Loggers.Where(x => x.Selected).Select(x => x.Id).ToArray();
var loggers_to_add = context.logger.Where(x => ids.Contains(x.id));
loggers_to_add.ToList().ForEach(x =>
{
    selectedAppender.logger.Add(x);
});

One downside to linq is you have to approach these types of problems iteratively. There is no way I know of to do a bulk delete. If you know of a way and can improve on it please share it.

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