[英]EF core computed properties marked as readonly
背景:每當添加或更新“Item”實體時,我都會覆蓋 SaveChanges() 方法以自動生成 LastUpdatedDate。
項目.cs
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime? LastUpdated { get; set; }
數據庫上下文
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
...
// generated value
modelBuilder.Entity<Item>()
.Property(b => b.LastUpdated)
.ValueGeneratedOnAddOrUpdate();
}
public override int SaveChanges()
{
var now = DateTime.UtcNow;
foreach (var item in ChangeTracker.Entries<Item>()
.Where(e => e.State == EntityState.Added || e.State == EntityState.Modified))
{
item.Property("LastUpdated").CurrentValue = now;
}
return base.SaveChanges();
}
我遇到的問題是每當調用 SaveChanges() 時,我都會收到此異常:
EntityFramework.Core.dll 中發生了“System.InvalidOperationException”類型的異常,但未在用戶代碼中處理。
附加信息:實體類型“Item”上的屬性“LastUpdated”在保存后被定義為只讀,但其值已被修改或標記為已修改。
要解決此問題,我必須將 IsReadOnlyBeforeSave 和 IsReadOnlyAfterSave 設置為 false,如下所示:
modelBuilder.Entity<Tray>()
.Property(b => b.LastUpdated)
.ValueGeneratedOnAddOrUpdate()
.Metadata.IsReadOnlyBeforeSave = false;
modelBuilder.Entity<Tray>()
.Property(b => b.LastUpdated)
.Metadata.IsReadOnlyAfterSave = false;
問題:
這是在 EF Core 中設置計算屬性的正確方法嗎?
此外,我可以首先防止將 LastUpdated 定義為“只讀”嗎?
這是在 EF Core 中設置計算屬性的正確方法嗎?
文檔對此非常清楚:
添加或更新時生成的值意味着每次保存(插入或更新)記錄時都會生成一個新值。
注意
如何為添加和更新的實體生成值將取決於所使用的數據庫提供程序。 (...) 如果您指定在添加或更新時生成 DateTime 屬性,則必須設置生成值的方法(例如數據庫觸發器)。
注釋的名稱 --"DatabaseGeneratedOption"-- 可能揭示了這些方面的內容。
所以如果你想使用這種模式,你應該在數據庫中設置一個觸發器,在插入和每次更新時設置字段值。 通過使用注釋[DatabaseGenerated]
或流暢的 API .ValueGeneratedOnAddOrUpdate()
(無需同時執行這兩項操作),EF 會收到信號,表示它應該在保存更改后從數據庫讀取值。
至於IsReadOnlyBeforeSave
屬性。 到目前為止,唯一的文檔是 EF 源代碼中有關該屬性的 XML 文檔:
獲取或設置一個值,該值指示在將實體保存到數據庫之前是否可以修改此屬性。 如果為 true,則在此屬性處於已
Added
狀態時為其分配值將引發異常。
據我所知,您可能希望將此值設置為true
以消除對設置此屬性有用的任何期望(因為它不是)。 同樣,您可以將IsReadOnlyAfterSave
設置為在現有(未Added
)實體中設置該屬性時引發異常。
如果您不想要數據庫生成的值,您可以刪除注釋並像現在一樣分配值。
IsReadOnlyAfterSave標志已被廢棄並由AfterSaveBehavior取代。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Device>()
.Property<string>("TenantId")
.HasField("_tenantId")
//.Metadata.IsReadOnlyAfterSave = true;
.Metadata.AfterSaveBehavior = Microsoft.EntityFrameworkCore.Metadata.PropertySaveBehavior.Ignore;
}
這是在 EF Core 5 中設置 AfterSaveBehavior 的方式
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MyEntity>
.Property(x => x.DateCreated)
.Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Save);
}
如果設置了顯式值或更改了值,則會引發異常。 這是默認設置,也是您收到異常的原因 - 根據您的情況將其設置為保存或忽略。
設置或更改的值將以正常方式發送到數據庫。
任何設置或更改的值都將被忽略。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.