Entity Framework Core 中违反 PRIMARY KEY 约束
Violation of PRIMARY KEY constraint in Entity Framework Core
我有一个使用 EFCore5 的 .NET5 Blazor 服务器应用程序。
我有两个彼此具有多对多关系的实体。
我们称它们为 'Books' 和 'Tags'.
EFCore 提供 BookTag 连接 table.
在我的页面上,我有一个表格,其中填充了书籍的详细信息,并且有一个用于标签的多 select 框。
当我拿到这本书时,我附上了标签:
context.Books.Include(x=>x.Tags);
在调试模式下,我看到 Book 项目有几个标签。但是当我更新书籍的一些细节并保存表格时,调用 context.Books.Update(book);
我得到一个错误,因为 BookTag 连接中的重复键 table.
似乎 EFCore 试图在 table 中插入条目,但它应该进行合并或 insert/update.
我读过很多关于多对多的文章,但它们都只是展示了如何检索数据。我找不到如何更新的示例。
编辑:
正如@carl-franklin 在他出色的 BlazorTrain 系列中所解释的那样,我正在使用 GenericRepository。
编辑2:
这是一些相关代码,我现在不使用 GenericRepo:
Startup.cs
services.AddDbContextFactory<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DbConnection")));
ApplicationDbContext.cs 只有 DbSet
个。
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();
}
即使我不做任何更改,只是更新我也会收到重复错误:
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'
在 UpdateBook() 中,我看到这本书有标签,正如预期的那样。看起来 EFCore 正在将它们插入连接 table 而没有检查它们是否已经存在。
更改跟踪必须打开才能工作。否则,您必须自己跟踪更改; Entity Framework 认为您正在添加新记录,但密钥与现有记录相同,这就是您收到错误的原因。
我有一个使用 EFCore5 的 .NET5 Blazor 服务器应用程序。
我有两个彼此具有多对多关系的实体。
我们称它们为 'Books' 和 'Tags'.
EFCore 提供 BookTag 连接 table.
在我的页面上,我有一个表格,其中填充了书籍的详细信息,并且有一个用于标签的多 select 框。
当我拿到这本书时,我附上了标签:
context.Books.Include(x=>x.Tags);
在调试模式下,我看到 Book 项目有几个标签。但是当我更新书籍的一些细节并保存表格时,调用 context.Books.Update(book);
我得到一个错误,因为 BookTag 连接中的重复键 table.
似乎 EFCore 试图在 table 中插入条目,但它应该进行合并或 insert/update.
我读过很多关于多对多的文章,但它们都只是展示了如何检索数据。我找不到如何更新的示例。
编辑:
正如@carl-franklin 在他出色的 BlazorTrain 系列中所解释的那样,我正在使用 GenericRepository。
编辑2:
这是一些相关代码,我现在不使用 GenericRepo:
Startup.cs
services.AddDbContextFactory<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DbConnection")));
ApplicationDbContext.cs 只有 DbSet
个。
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();
}
即使我不做任何更改,只是更新我也会收到重复错误:
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'
在 UpdateBook() 中,我看到这本书有标签,正如预期的那样。看起来 EFCore 正在将它们插入连接 table 而没有检查它们是否已经存在。
更改跟踪必须打开才能工作。否则,您必须自己跟踪更改; Entity Framework 认为您正在添加新记录,但密钥与现有记录相同,这就是您收到错误的原因。