2016-01-03 18 views
6

Sto trasferendo un vecchio progetto su ASP.NET 5 e Entity Framework 7. Ho utilizzato il primo approccio del database (scaffold DNX) per creare il modello.Registro di controllo di Entity Framework 7

Il vecchio progetto si basa su Entity Framework 4 e il monitoraggio di controllo è implementata tramite l'override del metodo SaveChanges del DbContext:

public override int SaveChanges(System.Data.Objects.SaveOptions options) 
{ 
    int? UserId = null; 
    if (System.Web.HttpContext.Current != null) 
     UserId = (from user in Users.Where(u => u.UserName == System.Web.HttpContext.Current.User.Identity.Name) select user.Id).SingleOrDefault(); 

    foreach (ObjectStateEntry entry in ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified)) 
    { 
     Type EntityType = entry.Entity.GetType(); 

     PropertyInfo pCreated = EntityType.GetProperty("Created"); 
     PropertyInfo pCreatedById = EntityType.GetProperty("CreatedById"); 
     PropertyInfo pModified = EntityType.GetProperty("Modified"); 
     PropertyInfo pModifiedById = EntityType.GetProperty("ModifiedById"); 

     if (entry.State == EntityState.Added) 
     { 
      if (pCreated != null) 
       pCreated.SetValue(entry.Entity, DateTime.Now, new object[0]); 
      if (pCreatedById != null && UserId != null) 
       pCreatedById.SetValue(entry.Entity, UserId, new object[0]); 
     } 
     if (pModified != null) 
      pModified.SetValue(entry.Entity, DateTime.Now, new object[0]); 
     if (pModifiedById != null && UserId != null) 
      pModifiedById.SetValue(entry.Entity, UserId, new object[0]); 
     } 
    } 

    return base.SaveChanges(options); 
} 

La mia domanda è: come posso implementare questo in Entity Framework 7? Devo prendere il primo approccio del codice?

+0

EF7 è lungi dall'essere finito e non pronto per la produzione. Prenderò prima le API EF6 e DbContext. Ci sono ancora molti articoli sul backlog EF7 che devono essere implementati prima che siano abbastanza maturi. –

+0

La mia comprensione è che si potrebbe implementarlo esattamente allo stesso modo ... o sostanzialmente lo stesso. – Seabizkit

+0

Personalmente dovresti passare l'id utente in un metodo, piuttosto che fare riferimento a System.Web in un livello correlato ai dati. – Seabizkit

risposta

5

Fondamentalmente ci sono due modi per raggiungere questo obiettivo:

Uso ChangeTracker API (EF 6+):

Questo è il modo in cui attualmente facciamo in EF 6 ed è ancora valido e funzionante per EF 7:

Prima di tutto bisogna assicurarsi che le entità stanno implementando un'interfaccia comune per i campi di audit:

public interface IAuditableEntity 
{ 
    int? CreatedById { get; set; } 

    DateTime Created { get; set; } 

    int? ModifiedById { get; set; } 

    DateTime Modified { get; set; } 
} 


Poi si può ignorare SaveChanges e aggiornare ogni campo comune con i valori di audit:

public override int SaveChanges() 
{ 
    int? userId = null; 
    if (System.Web.HttpContext.Current != null) 
     userId = (from user in Users.Where(u => u.UserName == System.Web.HttpContext.Current.User.Identity.Name) select user.Id).SingleOrDefault(); 

    var modifiedEntries = ChangeTracker.Entries<IAuditableEntity>() 
      .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified); 

    foreach (EntityEntry<IAuditableEntity> entry in modifiedEntries) 
    { 
     entry.Entity.ModifiedById = UserId; 
     entry.Entity.Modified = DateTime.Now; 

     if (entry.State == EntityState.Added) 
     { 
      entry.Entity.CreatedById = UserId; 
      entry.Entity.Created = DateTime.Now; 
     } 
    } 

    return base.SaveChanges(); 
} 


Utilizzando EF 7 nuova funzione "Proprietà Shadow":

Shadow properties sono proprietà che non esistono nella tua classe di entità. Il valore e lo stato di queste proprietà sono mantenuti puramente nel Change Tracker.

In altre parole, le colonne di controllo non verranno esposte sulle entità che sembrano essere un'opzione migliore rispetto a quella sopra in cui è necessario includerle nelle entità.

Per implementare le proprietà delle ombre, è necessario prima configurarle sulle entità. Diciamo per esempio si dispone di un oggetto utente che ha bisogno di avere alcune colonne di revisione:

protected override void OnModelCreating(ModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<User>().Property<int>("CreatedById"); 

    modelBuilder.Entity<User>().Property<DateTime>("Created"); 

    modelBuilder.Entity<User>().Property<int>("ModifiedById"); 

    modelBuilder.Entity<User>().Property<DateTime>("Modified"); 
} 


Una volta configurato, ora è possibile accedervi dal SaveChanges() Azionamento e aggiornare i loro valori di conseguenza:

public override int SaveChanges() 
{ 
    int? userId = null; 
    if (System.Web.HttpContext.Current != null) 
     userId = (from user in Users.Where(u => u.UserName == System.Web.HttpContext.Current.User.Identity.Name) select user.Id).SingleOrDefault(); 

    var modifiedBidEntries = ChangeTracker.Entries<User>() 
     .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified); 

    foreach (EntityEntry<User> entry in modifiedBidEntries) 
    { 
     entry.Property("Modified").CurrentValue = DateTime.UtcNow; 
     entry.Property("ModifiedById").CurrentValue = userId; 

     if (entry.State == EntityState.Added) 
     { 
      entry.Property("Created").CurrentValue = DateTime.UtcNow; 
      entry.Property("CreatedById").CurrentValue = userId; 
     } 
    } 

    return base.SaveChanges(); 
} 


Considerazioni finali:

Per implementare qualcosa di simile a colonne di audit, mi prendo la L'approccio di Shadow Properties poiché questi sono problemi trasversali e non appartengono necessariamente agli oggetti del mio dominio, quindi farli implementare in questo modo manterrà gli oggetti del mio dominio belli e puliti.

+0

Potresti aiutarmi a verificare la relazione eliminata e m-m usando l'API EF6 per favore? –

0

Ho lavorato su una libreria che potrebbe aiutare.

Dai un'occhiata alla libreria Audit.EntityFramework, intercetta SaveChanges() ed è compatibile con le versioni EF Core.

Problemi correlati