.NET 5.0 Razor Pages CRUD删除触发SQLite外键约束错误如何解决
问题根因
你遇到的SQLite外键约束报错,核心原因是你要删除的Album对象关联了Track表的子数据:
- Track表中存在
AlbumId外键字段,指向Album表的AlbumId主键 - 直接删除Album时,关联的Track数据的外键会失去关联目标,触发SQLite的外键约束校验失败
除此之外你的代码还存在两处明显问题:
- Delete.cshtml页面的Model绑定错误,绑定了
DetailsModel而非DeleteModel - Album实体的导航属性配置错误,一个专辑仅对应一个艺术家,不应配置为
ICollection<Artist>集合类型
修复方案
方案1:删除Album前先清空关联的Track数据
修改Delete.cshtml.cs的OnPostAsync方法,加载Album时同步加载关联的Track,先删除子数据再删除Album:
public async Task<IActionResult> OnPostAsync(int? id) { if (id == null) { return NotFound(); } // 加载Album时包含关联的Track集合 Album = await _context.albums.Include(a => a.tracks).FirstOrDefaultAsync(a => a.AlbumId == id); if (Album != null) { // 先批量删除关联的所有Track _context.tracks.RemoveRange(Album.tracks); // 再删除Album _context.albums.Remove(Album); await _context.SaveChangesAsync(); } return RedirectToPage("./Index"); }
方案2:配置EF Core外键级联删除(推荐)
在ChinookAppContext的OnModelCreating方法中配置外键级联删除规则,删除Album时EF会自动清理关联的子数据,同时修正Album和Artist的导航关系:
protected override void OnModelCreating(ModelBuilder modelBuilder) { // 配置Album和Track的级联删除 modelBuilder.Entity<Track>() .HasOne<Album>() .WithMany(a => a.tracks) .HasForeignKey(t => t.AlbumId) .OnDelete(DeleteBehavior.Cascade); // 修正Album和Artist的导航关系 modelBuilder.Entity<Album>() .HasOne<Artist>(a => a.Artist) .WithMany(ar => ar.Albums) .HasForeignKey(a => a.ArtistId) .OnDelete(DeleteBehavior.Restrict); }
同步修正Album实体的导航属性:
public class Album { public int AlbumId { get; set; } public string Title { get; set; } public int ArtistId { get; set; } public ICollection<Track> tracks { get; set; } // 将集合类型改为单个Artist对象 public Artist Artist { get; set; } }
方案3:修复Delete.cshtml的Model绑定
将Delete.cshtml第一行的Model声明修正为DeleteModel:
@page @model ChinookApp.Pages_Albums.DeleteModel @* 剩余页面内容保持不变即可 *@
内容的提问来源于stack exchange,提问作者Luca
相关产品推荐
相关产品推荐

