簡體   English   中英

SQLite EF Core -“外鍵約束失敗”

[英]SQLite EF Core - 'FOREIGN KEY constraint failed'

在我的 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; }
}

我在 DbContext 中的DbContext OnModelCreating方法:

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

從自動生成的遷移 class:

            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();
        }

我在嘗試刪除一條與另一個 object 一對多關系的記錄時遇到了同樣的錯誤。

問題是在 DataContext 中未定義級聯刪除,您可以將以下內容添加到 DataContext 中:

            
 modelbuilder.Entity<ObjectTypeModel>()
                .HasMany(dm => dm.Objects)
                .WithOne()
                .OnDelete(DeleteBehavior.Cascade);

您的模型和遷移已更正。 主要原因是SaveChangesAsyn時。

 TypeId = table.Column<int>(nullable: false)

從這里我們可以看到,FK( TypeId ) 不可為空。 因此,您應該確認您的 FK( ObjectTypeTypeId )不是 null 並且在添加新的 Object 時存在。

這是我添加 Object 的代碼,型號與您相同。

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; }
    }

我有同樣的問題,我必須使一個字段可以為空

這是一個示例,這為我解決了這個問題:

改變這個:

public int TypeId { get; set; }

對此:

public int? TypeId { get; set; }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM