SQLite EF Core - 'FOREIGN KEY 约束失败'

brs*_*tkr 5 c# sqlite entity-framework-core asp.net-core

在我的 ASP.Net Core 项目中,我在启动时遇到了这个异常,因为我正在运行时初始化数据库:

失败:Microsoft.EntityFrameworkCore.Update[10000]

保存上下文类型“BlazorWeb.Server.Data.SQLiteTestDbContext”的更改时,数据库中发生异常。
Microsoft.EntityFrameworkCore.DbUpdateException:更新条目时出错。有关详细信息,请参阅内部异常。

Microsoft.Data.Sqlite.SqliteException (0x80004005):SQLite 错误 19:“外键约束失败”。

在 Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db)
....

我的模型:

public class ObjectModel : BaseEntity
{
    [Key]
    public int Id { get; set; }
    public String Name { get; set; }
    public String PreviewImage { get; set; }
    public String  TagName { get; set; }

    // Foreign keys---
    public int TypeId { get; set; }
    public ObjectTypeModel TypeModel { get; set; }
    //---
}

public class ObjectTypeModel : BaseEntity
{
    [Key]
    public int TypeId { get; set; }
    public String Name { get; set; }
    public String PreviewImage { get; set; }
    public String TagName { get; set; }

    public ICollection<ObjectModel> Objects { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我的 SQLiteOnModelCreating方法在DbContext

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<ObjectModel>()
      .HasOne<ObjectTypeModel>(d => d.TypeModel)
      .WithMany(dm => dm.Objects)
      .HasForeignKey(dkey => dkey.TypeId);
}
Run Code Online (Sandbox Code Playgroud)

从自动生成的迁移类:

            name: "Objects",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("Sqlite:Autoincrement", true),
                CreatedOn = table.Column<DateTime>(nullable: false),
                ModifiedOn = table.Column<DateTime>(nullable: false),
                Name = table.Column<string>(nullable: true),
                PreviewImage = table.Column<string>(nullable: true),
                TagName = table.Column<string>(nullable: true),
                TypeId = table.Column<int>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Objects", x => x.Id);
                table.ForeignKey(
                    name: "FK_Objects_ObjectTypes_TypeId",
                    column: x => x.TypeId,
                    principalTable: "ObjectTypes",
                    principalColumn: "TypeId",
                    onDelete: ReferentialAction.Cascade);
            });
Run Code Online (Sandbox Code Playgroud)

在我的 initialize 方法中,我只用一些数据填充它并将它们保存到上下文中。但是数据库永远不会收到这些记录,也会发生外键约束异常。

任何人都可以帮助我 - 我做错了什么吗?

编辑 我发现异常发生在 SaveChangeAsync() 方法运行时之后。我的覆盖SaveChangesAsyn()方法:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<ObjectModel>()
      .HasOne<ObjectTypeModel>(d => d.TypeModel)
      .WithMany(dm => dm.Objects)
      .HasForeignKey(dkey => dkey.TypeId);
}
Run Code Online (Sandbox Code Playgroud)

小智 8

我在尝试删除与另一个对象具有一对多关系的一条记录时遇到了同样的错误。

问题是在 DataContext 中未定义级联删除,您可以将以下内容添加到 DataContext 中:

            
 modelbuilder.Entity<ObjectTypeModel>()
                .HasMany(dm => dm.Objects)
                .WithOne()
                .OnDelete(DeleteBehavior.Cascade);
Run Code Online (Sandbox Code Playgroud)


Mic*_*ang 1

您的模型和迁移已得到纠正。主要原因是当SaveChangesAsyn.

 TypeId = table.Column<int>(nullable: false)
Run Code Online (Sandbox Code Playgroud)

从这里我们可以看到,FK( TypeId) 不可为空。因此,当您添加新对象时,您应该确认您的 FK( TypeIdof ObjectType) 不为空并且存在。

这是我添加对象的代码,模型与您相同。

public async Task<IActionResult> Create([Bind("Id,content,Deadline,IsComplete,UserId")] ToDoItem toDoItem)
        {
            if (ModelState.IsValid)
            {
                _context.Add(toDoItem);
                await _context.SaveChangesAsync();

            }
            return View();
        }
Run Code Online (Sandbox Code Playgroud)

型号代码如下。

public class ToDoItem
    {
        public int Id { get; set; }
        public string content { get; set; }
        public DateTime Deadline { get; set; }
        public bool IsComplete { get; set; }

        public int UserId { get; set; }
        public User user { get; set; }
    }

public class User
    {
        public int Id { get; set; }
        public string username { get; set; }
        public string password { get; set; }
        public ICollection<ToDoItem> ToDoItems { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)