简体   繁体   中英

EF Core 5 - Many to Many - remove

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 .

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