'EF Core - generic way to merge child records based on current db state and equality
I have a scenario where during an Update request of a parent entity, I have a collection of children entities in my dto, and want to merge them in the DB so that it either:
- Replaces it if something changed.
- Adds it if it doesn't already exist.
- Deletes it if it doesn't exist in the dto.
Front-end: my page allows you to edit the name of the book and add/edit/delete genres associated with the book. I have a data grid to manage the genres collection of a book and the ids are created on the client using guids, they'll always be unique across all scenarios.
An example of the js object that is sent up to a controller is like:
const bookState = {
id: "xx-xx-xx",
title: "Title X",
genres: [{
id: "xx-xx-xx",
name: "sci-fi"
},
{
id: "xxx-xx",
name: "autobiography},
]
}
Entities:
public class Book
{
public Guid Id { get; set; }
public string Title { get; set; }
public List<Genre> genres { get; set; } = new();
}
public class Genre
{
public Guid Id { get; set; }
public string Name {get; set;}
}
Here's the Update method where I would like to handle this entity and its children:
public async Task UpdateBook (Request request, CancellationToken cancellationToken)
{
Book? entity = await _context.Books
.Include(b => b.Genres)
.FirstOrDefaultAsync(b => b.Id == request.Id, cancellationToken);
if (entity == null)
{
// return book not found
}
entity.Title = request.Book.Title;
// remove genres in db that are not in the request (ie, they were deleted from user)
entity.Genres.RemoveAll(x => !request.Book.Genres.Select(r => r.Id).Contains(x.Id));
//new ones to add
var newGenres = request.Book.Genres.Where(x => !entity.Genres.Select(r => r.Id).Contains(x.Id));
foreach (var item in newGenres)
{
_context.Genres.Add(new Genre(item.Id, item.Name, request.Id));
}
// LINQ to get the list of existing genres on this entity so I
// could iterate through them and update the individual fields for each one in
// the request that matches?
_context.Update(entity)
_context.SaveChangesAsync(cancellationToken);
}
What would the linq query be to update the existing genres ?
I'm using EF Core 6 code-first. First time with this, it just seems like it would be easier-but maybe this is an unusual use case.
Thanks
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|