Utilizzare le annotazioni nei metadati di Entity Framework Core per marcare campi come non modificabili

di Stefano Mostarda, in LINQ, Entity Framework,

Quando inseriamo un record nel database, abbiamo spesso l'esigenza di dover calcolare e salvare dei dati che poi non devono più essere modificabili dall'applicazione. Un tipico esempio di questo tipo di dati sono la data di creazione, il codice matricola assegnato a un dipendente quando viene assunto, la partita iva di una nuova azienda, il tenantid di un'applicazione multitenant e così via. In questi casi dobbiamo assicurarci che quando aggiorniamo il record, questi dati non siano mai modificati.
Per garantirci questa funzionalità, possiamo sfruttare le annotazioni di Entity Framework in fase di mapping e seguire il seguente flusso:

  • Creare un'annotazione con la quale marcare le proprietà non modificabili;
  • Marcare le proprietà non modificabili con questa annotazione;
  • In fase di salvataggio, scorrere le proprietà delle entity modificate e impostare come non modificate quelle marcate dall'annotazione.

Grazie a questa tecnica, qualunque sia il codice che viene scritto, il DbContext ci assicurerà che le proprietà non modificabili non saranno mai modificate.

Il primo passo consiste nel creare l'annotazione. Una annotazione è semplicemente una stringa che possiamo associare ai metadati di una classe, di una proprietà, di una reference o altro ancora.

public static class Annotations
{
  public const string CannotBeUpdated = nameof(CannotBeUpdated);
}

Il secondo passo consiste nel marcare la proprietà come non modificabile aggiungendo a questa l'annotazione appena creata.

modelBuilder.Entity<Person>(entity =>
{
  ...
  entity.Property(p => p.TenantId)
    .HasAnnotation(Annotations.CannotBeUpdated, true);
});

Come ultimo passo, dobbiamo eseguire l'override del metodo SaveChanges del nostro DbContext, recuperare le entity in stato Modified, per ognuna di queste recuperare le prorietà in stato Modified che hanno anche l'annotazione e portarne lo stato a Unchanged.

public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
  var modifiedEntries = ChangeTracker.Entries()
    .Where(e => e.State == EntityState.Modified)
    .ToList();

  foreach (var entry in modifiedEntries)
  {
    foreach (var property in entry.Properties.Where(c => c.IsModified).ToList())
    {
      if (property.Metadata.FindAnnotation(Annotations.CannotBeUpdated) != null)
      {
        property.IsModified = false;
      }
    }
  }
}

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi