代码之家  ›  专栏  ›  技术社区  ›  noblerare

将EF核心列/字段指定为只读

  •  2
  • noblerare  · 技术社区  · 7 年前

    我有一个SQL Server表,其中包含由数据库通过默认值设置的某些字段,这些默认值保存后应 从不 DateCreated ).

    在Entity Framework Core 2.1 model builder或类中,如何将字段“标记”为只读字段?换句话说,我不希望任何代码能够设置或覆盖这些字段。

    根据我的搜索,我会添加 .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
        });
    }
    

    或者我要添加一个 [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 日期创建

    public class Doohicky
    {
        public DateTime DateCreated {get; set;}
    }
    

    还是完全有另一种方式?

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

    model.DateCreated = new DateTime();
    dbContext.SaveChanges() // errors out
    

    3 回复  |  直到 7 年前
        1
  •  12
  •   Community Mohan Dere    6 年前

    EF核心的预期方式是设置 AfterSaveBehavior Save :

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

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

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

    更新(EF Core 3.x): 从EF Core 3.0开始,许多类似的属性已被替换为 Get / Set 扩展方法对,因此现在相关代码如下:

        .Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Throw); 
    
        2
  •  1
  •   Mohamed Elrashid    7 年前
    [Required, DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DateTime DateCreated {get; set;}
    
        3
  •  0
  •   Mark Meisel    7 年前

    我以前使用可审核属性(如DateCreated、DateModified等)进行过此操作。此解决方案可能不适合在各种对象中排除特定属性(尽管您可能可以使用自定义属性等)。

    我重写SaveChanges/Async(),然后遍历上下文正在跟踪的所有已更改对象。我的所有对象都使用相同的基类,因此我可以通过以下方式实现这一点:

    var changes = ChangeTracker.Entries<BaseEntity>().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified);
    

    // A collection of property names which should not be updated
    var excludedProperties = new[] { "CreatedBy", "CreatedDateUtc" };
    
    foreach (var change in changes)
    {
       // If new, do as you'd like
    
       // If used, ignore date created
       Array.ForEach(excludedProperties, prop =>
       {
          change.Property(prop).IsModified = false;
       });
    }