SQLite EF Core - '外键约束失败'
Posted
技术标签:
【中文标题】SQLite EF Core - \'外键约束失败\'【英文标题】:SQLite EF Core - 'FOREIGN KEY constraint failed'SQLite EF Core - '外键约束失败' 【发布时间】:2020-10-18 21:39:26 【问题描述】:在我的 ASP.Net Core 项目中,我在启动时遇到了这个异常,因为我在运行时初始化数据库:
失败:Microsoft.EntityFrameworkCore.Update[10000]
保存上下文类型“BlazorWeb.Server.Data.SQLiteTestDbContext”的更改时,数据库中发生异常。 Microsoft.EntityFrameworkCore.DbUpdateException:更新条目时出错。有关详细信息,请参阅内部异常。
Microsoft.Data.Sqlite.SqliteException (0x80004005):SQLite 错误 19:“FOREIGN KEY 约束失败”。
在 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;
DbContext
中的My SQLite OnModelCreating
方法:
protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity<ObjectModel>()
.HasOne<ObjectTypeModel>(d => d.TypeModel)
.WithMany(dm => dm.Objects)
.HasForeignKey(dkey => dkey.TypeId);
来自自动生成的迁移类:
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);
);
在我的初始化方法中,我只是用一些数据填充它并将它们保存到上下文中。但是数据库永远不会收到这些记录,并且还会发生外键约束异常。
任何人都可以帮助我 - 我做错了什么吗?
编辑
我发现在 SaveChangeAsync() 方法运行后发生异常。
我重写的SaveChangesAsyn()
方法:
public Task<int> SaveChangesAsync()
var entries = ChangeTracker
.Entries()
.Where(e => e.Entity is BaseEntity && (
e.State == EntityState.Added ||
e.State == EntityState.Modified));
foreach (var entityEntry in entries)
// overwrite `ModifiedOn` value with current date.
((BaseEntity)entityEntry.Entity).ModifiedO=
DateTime.Now;
// set `CreatedOn` to current date if its not already set.
if (entityEntry.State == EntityState.Added)
((BaseEntity)entityEntry.Entity).CreatedOn = DateTime.Now;
return base.SaveChangesAsync();
【问题讨论】:
当您将ObjectModel
的public int TypeId get; set;
更改为public int TypeModelId get; set;
时会发生什么?
@JKL 在ObjectType.cs
中将其更改为 TypeModelId,但没有任何改变。还进行了新的迁移和数据库更新。
【参考方案1】:
我在尝试删除与另一个对象具有一对多关系的记录时遇到了同样的错误。
问题是在 DataContext 中未定义级联删除,您可以将以下内容添加到 DataContext:
modelbuilder.Entity<ObjectTypeModel>()
.HasMany(dm => dm.Objects)
.WithOne()
.OnDelete(DeleteBehavior.Cascade);
【讨论】:
【参考方案2】:您的模型和迁移已更正。主要原因是当SaveChangesAsyn
。
TypeId = table.Column<int>(nullable: false)
从这里我们可以看到,FK(TypeId
) 不能为空。所以你应该确认你的FK(ObjectType
的TypeId
)不为空并且在你添加新对象时存在。
这是我添加对象的代码,模型和你一样。
public async Task<IActionResult> Create([Bind("Id,content,Deadline,IsComplete,UserId")] ToDoItem toDoItem)
if (ModelState.IsValid)
_context.Add(toDoItem);
await _context.SaveChangesAsync();
return View();
型号代码如下。
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;
【讨论】:
以上是关于SQLite EF Core - '外键约束失败'的主要内容,如果未能解决你的问题,请参考以下文章
EF Core / Sqlite 一对多关系在唯一索引约束上失败
Django 2.0:sqlite IntegrityError:外键约束失败