Specify EF Core column/field as read only

前端 未结 3 973
情深已故
情深已故 2020-12-06 19:01

I have a SQL Server table with certain fields that are set by the database via default values that, once saved, should never been modified again (e.g.

相关标签:
3条回答
  • 2020-12-06 19:44
    [Required, DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DateTime DateCreated {get; set;}
    
    0 讨论(0)
  • 2020-12-06 19:50

    I've done this in the past with auditable properties such as DateCreated, DateModified, etc. This solution probably isn't ideal for excluding specific properties in various objects (although you could probably do something with a custom attribute, etc.).

    I override SaveChanges/Async(), then loop through all the changed objects that the context is tracking. All of my objects use the same base class so I can achieve this through the following:

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

    With those objects, I loop over them and set some auditable properties, or ignore certain properties if the object isn't new. First, I have a collection of strings which represent property names that I want to exclude. I then loop over the collection and ignore the properties where the property name matches that of the excluded collection. See below:

    // 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;
       });
    }
    
    0 讨论(0)
  • 2020-12-06 19:53

    The EF Core intended way is to set AfterSaveBehavior property to value other than the default Save:

    Gets a value indicating whether or not this property can be modified after the entity is saved to the database.

    If Throw, then an exception will be thrown if a new value is assigned to this property after the entity exists in the database.

    If Ignore, then any modification to the property value of an entity that already exists in the database will be ignored.

    There is no dedicated fluent API yet, so you need to set it directly through mutable property metadata like this:

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

    Update (EF Core 3.x): Starting with EF Core 3.0, many properties like this have been replaced with Get / Set extension method pairs, so the relevant code now is as follows:

        .Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Throw); 
    
    0 讨论(0)
提交回复
热议问题