I am using new feature of EF Core 5 where I dont have to specify many-to-many class by myself and instead let it do for EF itself.
I have a simple classes:
UserMap:
public class UserMap : IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> builder)
{
builder.HasKey(x => x.Id);
builder.HasMany(x => x.Favorites).WithMany(x => x.Followers);
}
}
public class RecipeProviderMap : IEntityTypeConfiguration<RecipeProvider>
{
public void Configure(EntityTypeBuilder<RecipeProvider> builder)
{
builder.HasKey(x => x.Id);
builder.HasMany(x => x.Followers).WithMany(x => x.Favorites);
}
}
And of course collections in each class like:
public ICollection<User> Followers { get; set; }
public ICollection<RecipeProvider> Favorites { get; set; }
If I want to add an follower to RecipeProvider class I do:
var recipeProvider = await _dataProvider
.RecipeProviders
.Include(x => x.Followers)
.FirstOrDefaultAsync(x => x.Id == request.RecipeProviderId, cancellationToken);
if (recipeProvider == null)
return Unit.Value;
recipeProvider.AddAsFavorite(user);
_dataWriter.Update(recipeProvider);
await _dataWriter.SaveChangesAsync();
Not that line HAS to be added
_dataWriter.Update(recipeProvider);
So above example work for adding but I have problem with removing and I tried a lot of different options. The proposal looks like:
var user = await
_dataProvider
.Users
.Include(x => x.Favorites)
.FirstOrDefaultAsync(x => x.Id == request.FollowerId, cancellationToken);
var provider = user.Favorites.FirstOrDefault(x => x.Id == request.RecipeProviderId);
user.Favorites.Remove(provider);
await _dataWriter.SaveChangesAsync();
And above code do not remove the entity. Am I missing something?
I took your code and made a similar model but with books and tags.
var tag = dbCotnext.Find<Tag>(1);
var book = dbCotnext.Find<Book>(1);
tag.Books.Add(book);
dbCotnext.SaveChanges();
tag.Books.Remove(book);
dbCotnext.SaveChanges();
I placed breakpoints after both SaveChanges and everything in the database looked as expected, I see the new entity in the BookTag table after hitting the first breakpoint and it vanishes after I hit the second.
However, I see something alerting in your code. You're using two contexts, one for reads _dataProvider
and the other for writes _dataWriter
. I think that if you would call SaveChanges
on the _dataProvider
it would work, but you call it on _dataWriter
where the entity you loaded from the other context is not tracked. You could explicitly load it to _dataWriter
and then remove the element from the collection and then save changes, so then SaveChanges
would work as expected on the _dataWriter
.
To sum up, I think that _dataWriter
is not tracking changes on the entity loaded by another context which is _dataProvider
.