Reputation: 3284
I have a .NET5 Blazor Server application using EFCore5.
I have two entities that have a many-to-many relationship with each other.
Let's call them 'Books' and 'Tags'.
EFCore provides the BookTag join table.
On my page, I have a form that is populated with the book details and has a multi select box for the tags.
I include the tags when I get the book:
context.Books.Include(x=>x.Tags);
In debug mode, I see the Book item has several tags. But when I update some details of the book and save the form, calling context.Books.Update(book);
I get an error because of duplicate keys in the BookTag join table.
It seems EFCore tries to insert entries in that table, but it should do a merge or insert/update.
I've read numerous articles about the many-to-many but all of them just show how to retrieve data. I can't find an example of how to update.
Edit:
I'm using the GenericRepository as explained by @carl-franklin in his excellent BlazorTrain series.
Edit2:
Here is some relevant code, I'm now not using the GenericRepo:
Startup.cs
services.AddDbContextFactory<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DbConnection")));
ApplicationDbContext.cs has only the DbSet
s.
Book.cs
[Key]
public string Code { get; set; }
public string Name { get; set; } = "";
public virtual ICollection<Tag> TagCollection { get; set; }
Tag.cs
[Key]
public string Code { get; set; }
public string Name { get; set; } = "";
public virtual ICollection<Book> BookCollection { get; set; }
Book.razor.cs
[Inject] private IDbContextFactory<ApplicationDbContext> contextFactory { get; set; }
private ApplicationDbContext context { get; set; }
protected IEnumerable<Book> BookList;
protected override async Task OnInitializedAsync()
{
context = contextFactory.CreateDbContext();
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
BookList = await context.Books.Include(x => x.TagCollection).ToListAsync();
}
private async Task UpdateBook(Book book)
{
// Called after submitting form
context.Books.Update(book);
await context.SaveChangesAsync();
}
Even if I don't change anything, just update I get the duplicate error:
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> Microsoft.Data.SqlClient.SqlException (0x80131904): Violation of PRIMARY KEY constraint 'PK_BookTag'. Cannot insert duplicate key in object 'dbo.BookTag'
In UpdateBook() I see the book has tags, as expected. It looks like EFCore is inserting them in the join table without checking if they already exist.
Upvotes: 0
Views: 3809
Reputation: 180788
Change tracking must be turned on for this to work. Otherwise, you have to track the changes yourself; Entity Framework thinks you're adding a new record, but the key is the same as an existing record, which is why you're getting the error.
Upvotes: 1