将 EF Core 列/字段指定为只读

nob*_*are 6 c# sql-server entity-framework entity-framework-core

我有一个由数据库中通过,一旦保存,应默认值设定某些字段一个SQL Server表从来没有再次被修改(例如DateCreated)。

在 Entity Framework Core 2.1 模型构建器或类中,我们如何将字段“标记”为本质上是只读的?换句话说,我不希望任何代码能够设置或覆盖这些字段。

根据我的搜索,我会.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)在末尾添加.Property()吗?

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Doohicky>(entity =>
    {
        ... // other fields

        entity.Property(e => e.DateCreated).HasDefaultValueSql("(getdate())");

        ... // other fields
    });
}
Run Code Online (Sandbox Code Playgroud)

或者我[DatabaseGenerated(DatabaseGeneratedOption.Identity)]是否向该DateCreated字段添加注释?

public class Doohicky
{
    public DateTime DateCreated {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

还是完全有另一种方式?

我希望将来如果有人决定写这样的东西,就会抛出错误。

model.DateCreated = new DateTime();
dbContext.SaveChanges() // errors out
Run Code Online (Sandbox Code Playgroud)

任何见解将不胜感激。

Iva*_*oev 11

EF Core 的预期方法是将AfterSaveBehavior属性设置为默认Save以外的值:

获取一个值,该值指示在将实体保存到数据库后是否可以修改此属性。

如果是Throw,则在实体存在于数据库中后,如果为此属性分配了新值,则会引发异常。

如果忽略,则对数据库中已存在的实体的属性值的任何修改都将被忽略。

目前还没有专用的 fluent API,因此您需要直接通过可变属性元数据进行设置,如下所示:

entity.Property(e => e.DateCreated)
    .HasDefaultValueSql("(getdate())")
    .Metadata.AfterSaveBehavior = PropertySaveBehavior.Throw; // <-- 
Run Code Online (Sandbox Code Playgroud)

更新(EF Core 3.x):从EF Core 3.0开始,很多像这样的属性已经被Get/Set扩展方法对替换了,所以现在相关代码如下:

    .Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Throw); 
Run Code Online (Sandbox Code Playgroud)

  • 这对我很有帮助!谢谢! (2认同)