我有一個Comment擁有的物體型別:
public class Comment { // owned entity type
public Comment(string text) { Text = text; }
public string Text { get; private set; }
}
public class Post {
public Post(string content) { Content = content; }
public long Id { get; private set; }
public string Content { get; private set; }
public ICollection<Comment> Comments { get; private set; } = new HashSet<Comment>();
}
AndPost的配置包括:
builder.OwnsMany(x => x.Comments, x => {
x.Property(y => y.Text).IsRequired();
});
播種代碼包括:
var post = new Post("content");
post.Comments.Add(new Comment("comment1"));
post.Comments.Add(new Comment("comment2"));
await _context.AddAsync(post);
await _context.SaveChangesAsync();
當我使用 postgres 提供程式時,我可以成功地創建、播種和編輯資料庫。
當我使用 sqlite 提供程式時,我可以成功創建資料庫,但是當我嘗試為其播種時,我收到此錯誤:
Microsoft.EntityFrameworkCore.DbUpdateException:更新條目時出錯。有關詳細資訊,請參閱內部例外。
---> Microsoft.Data.Sqlite.SqliteException (0x80004005):SQLite 錯誤 19:“非空約束失敗:Comment.Id”。
該檔案說,該擁有的表有一個隱含的關鍵,這也解釋了有關投訴Comment.Id。
但是為什么這只發生在 sqlite 上,我該如何解決呢?
uj5u.com熱心網友回復:
這是由 (1) 不正確的 (恕我直言) EF Core 默認值和 (2) 不受支持的 SQLite 功能的組合引起的。
- 如所擁有型別的集合EF Core 檔案中所述
擁有的型別需要一個主鍵。如果 .NET 型別沒有好的候選屬性,EF Core 可以嘗試創建一個。然而,當擁有的型別通過集合定義時,僅僅創建一個影子屬性來充當所有者的外鍵和擁有的實體的主鍵是不夠的,就像我們所做的那樣
OwnsOne:可以有多個每個所有者的擁有型別實體,因此所有者的密鑰不足以為每個擁有的實體提供唯一標識。
問題是,如果您沒有定義顯式 PK,那么 EF Core 會生成名為Id、型別int、自動增量的影子屬性(列)(他們認為,但是請參閱 (2))并在 (OwnerId, Id) 上定義復合PK
- 但是,SQLite僅當它是單個 PK 列時才支持自動增量列。因此,它生成常規
INTcolumnId,然后需要顯式值 onINSERT,但 EF Core 不會發送它,因為它仍然認為該屬性是在服務器上自動生成的。
話雖如此,您最好始終定義擁有的集合物體的 PK。由于自動增量本身是唯一的,絕對最小值是將自動生成的陰影Id屬性標記為 PK,例如
builder.OwnsMany(e => e.Comments, cb => {
cb.HasKey("Id"); // <-- add this
// The rest...
cb.Property(e => e.Text).IsRequired();
});
生成的遷移應該有列的“Sqlite:Autoincrement”注釋Id:
Id = table.Column<long>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
這是丟失并導致 OP 設計中的問題。
我個人更希望 EF Core 拋出常規的無鍵定義錯誤,而不是定義所有資料庫都不支持的 PK 構造。SQLite 提供程式也拋出例外而不是靜默忽略自動增量模型請求,從而引入模型元資料之間的差異(EF Core 基礎結構使用它來控制所有運行時行為)。因此,從技術上講,兩者都可以被視為錯誤。但他們就是他們。通常更喜歡約定而不是配置,但對于具有任意默認值的事物要明確。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/346782.html
標籤:C# sqlite 实体框架核心 ef-core-5.0
上一篇:如何從Cursor獲取Bool(JavaSQLite)
下一篇:選擇查詢消除不需要的行
