私は最初にデータベースファーストのアプローチでEFコードを使用しています。 "with Database.SetInitializer(null);"
私のテーブルには、createddateとamendddateの2つの列があります。これらは、トリガーを使用してSQLServerによって管理されます。データ入力が発生すると、これらの列はトリガーを介してデータを取得するという考え方です。
さて、私がやりたいのは、これをEFコードの最初の観点から読み取り専用にすることです。つまりアプリから作成日と修正日を確認できるようにしたいのですが、これらのデータを修正したくありません。
セッターでプライベート修飾子を使用しようとしましたが、うまくいきませんでした。テーブルに新しいデータを追加しようとすると、データベースにDateTime.Max日付を入力しようとしましたが、SQLサーバーからエラーがスローされます。
何か案が?
EF自体がエンティティのロード時にプロパティを設定する必要があり、Code Firstはプロパティにパブリックセッターがある場合にのみこれを行うことができるため、プライベート修飾子を使用することはできません(プライベートセッターが可能なEDMXとは対照的 (1) 、 (2) )。
CreatedDate
をDatabaseGeneratedOption.Identity
でマークし、AmendDate
をDatabaseGeneratedOption.Computed
でマークする必要があります。これにより、EFはデータベースからデータを正しくロードし、挿入または更新後にデータをリロードして、エンティティがアプリケーションで最新になるようにします。同時に、で設定された値のため、アプリケーションで値を変更することはできません。アプリケーションがデータベースに渡されることはありません。オブジェクト指向の観点からは、それはあまり良い解決策ではありませんが、機能の観点からは、まさにあなたが望むものです。
データ注釈を使用して、次のいずれかを実行できます。
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public DateTime CreatedDate { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime AmendDate { get; set; }
または、派生コンテキストでOnModelCreating
オーバーライドの流暢なAPIを使用します。
modelBuilder.Entity<YourEntity>()
.Property(e => e.CreatedDate)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<YourEntity>()
.Property(e => e.AmendDate)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
EFコア1.1以降のバージョンはい、pocoクラスで読み取り専用プロパティを使用できます。あなたがする必要があるのは、バッキングフィールドを使用することです。
public class Blog
{
private string _validatedUrl;
public int BlogId { get; set; }
public string Url
{
get { return _validatedUrl; }
}
public void SetUrl(string url)
{
using (var client = new HttpClient())
{
var response = client.GetAsync(url).Result;
response.EnsureSuccessStatusCode();
}
_validatedUrl = url;
}
}
class MyContext:DbContext {public DbSet Blogs {get;セットする; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(b => b.Url)
.HasField("_validatedUrl");
}
}
流暢なAPI ...
modelBuilder.Entity<Blog>()
.Property(b => b.Url)
.HasField("_validatedUrl")
.UsePropertyAccessMode(PropertyAccessMode.Field);