2016-09-01 3 views
1

背景: "Item"エンティティが追加または更新されるたびにLastUpdatedDateを自動的に生成するSaveChanges()メソッドをオーバーライドします。読み取り専用としてマークされたEFコアの計算されたプロパティ

Item.cs

[DatabaseGenerated(DatabaseGeneratedOption.Computed)] 
    public DateTime? LastUpdated { get; set; } 

DbContext

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'プロパティは、保存後に読み取り専用に定義されていますが、値が変更されたか、変更済みとしてマークされています。以下に示すように

は、この問題を回避するために、私は、falseにIsReadOnlyBeforeSaveとIsReadOnlyAfterSave を設定しなければならなかった:

 modelBuilder.Entity<Tray>() 
      .Property(b => b.LastUpdated) 
      .ValueGeneratedOnAddOrUpdate() 
      .Metadata.IsReadOnlyBeforeSave = false; 
     modelBuilder.Entity<Tray>() 
      .Property(b => b.LastUpdated) 
      .Metadata.IsReadOnlyAfterSave = false; 

質問:

が、これは計算された設定に正しい方法ですEFコアのプロパティ

さらに、最初の場所でLastUpdatedが「読み取り専用」として定義されないようにすることはできますか?

答えて

5

これは、EFコアで計算されたプロパティを設定する正しい方法ですか?

documentationは、この上の非常に明確である:追加または更新に生成さ

値が新しい値がレコードが保存されるたびに(挿入または更新)を発生させることを意味します。値が追加され、更新されたエンティティのために生成される方法

注意

が使用されているデータベース・プロバイダーに依存します。 (...)DateTimeプロパティがaddまたはupdateで生成されることを指定した場合、値の生成方法(データベーストリガなど)を設定する必要があります。

アノテーションの名前 - 「DatabaseGeneratedOption」 - これらの行に何かが現れている可能性があります。

このパターンを使用する場合は、挿入時および更新時にフィールド値を設定するデータベース内にトリガーを設定する必要があります。 [DatabaseGenerated]または流暢なAPI .ValueGeneratedOnAddOrUpdate()(両方を行う必要はありません)を使用すると、EFは変更を保存した後にデータベースから値を読み取るように通知します。

IsReadOnlyBeforeSaveについては、これまでの唯一のドキュメントは、EFのソースコード内のプロパティに関するXMLドキュメントです。

エンティティをデータベースに保存する前にこのプロパティを変更できるかどうかを示す値を取得または設定します。 trueの場合、Added状態にあるときに値がこのプロパティに割り当てられると、例外がスローされます。

このプロパティを設定することが有用であること(それがないので)私の知る限り見ることができるように、あなたはどんな期待を排除するためにtrueにこの値を設定することもできます。同様に、プロパティが既存のエンティティ(Addedではなく)に設定されている場合、IsReadOnlyAfterSaveに例外をスローするように設定できます。

データベース生成値を必要としない場合は、アノテーションを削除して今のように値を割り当てることができます。

+0

はい、私はデータベース上で生成していないため、アノテーションは不要でしたので、今すぐ取得します。しかし、Metadata.IsReadOnlyBeforeSave設定はどうでしょうか?計算されたプロパティごとに両方をfalseに設定することをお勧めしますか? – proggrock

+0

編集をご覧ください。 –

0

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; 
} 
関連する問題