簡體   English   中英

EF 核心計算屬性標記為只讀

[英]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 核心 3.x 和 5

這是在 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.

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