Sembra ignorare i ChangeChanges in EF per aggiungere un registratore di controllo. Vedere il metodo ApplyAuditLogging per impostare le proprietà di controllo (create, createby, updated, updatedby) di seguito.Entity Framework 5 Utilizzo di SaveChanges per aggiungere il registro di controllo
public override int SaveChanges()
{
var autoDetectChanges = Configuration.AutoDetectChangesEnabled;
try
{
Configuration.AutoDetectChangesEnabled = false;
ChangeTracker.DetectChanges();
var errors = GetValidationErrors().ToList();
if(errors.Any())
{
throw new DbEntityValidationException("Validation errors were found during save: " + errors);
}
foreach (var entry in ChangeTracker.Entries().Where(e => e.State == EntityState.Added || e.State == EntityState.Modified))
{
ApplyAuditLogging(entry);
}
ChangeTracker.DetectChanges();
Configuration.ValidateOnSaveEnabled = false;
return base.SaveChanges();
}
finally
{
Configuration.AutoDetectChangesEnabled = autoDetectChanges;
}
}
private static void ApplyAuditLogging(DbEntityEntry entityEntry)
{
var logger = entityEntry.Entity as IAuditLogger;
if (logger == null) return;
var currentValue = entityEntry.Cast<IAuditLogger>().Property(p => p.Audit).CurrentValue;
if (currentValue == null) currentValue = new Audit();
currentValue.Updated = DateTime.Now;
currentValue.UpdatedBy = "???????????????????????";
if(entityEntry.State == EntityState.Added)
{
currentValue.Created = DateTime.Now;
currentValue.CreatedBy = "????????????????????????";
}
}
Il problema è che come ottenere il finestre di accesso utente/nome utente per impostare le proprietà UpdatedBy e CreatedBy dell'oggetto? Quindi non potrei usare questo!
Inoltre, in un altro caso, ho voluto aggiungere automaticamente un nuovo record CallHistory al mio contatto; ogni volta che il contatto viene modificato, è necessario aggiungere un nuovo record alla tabella figlio CallHistory. Quindi l'ho fatto in InsertOrUpdate del repository ma sembra sporco, sarebbe bello se potessi farlo ad un livello più alto come ora devo impostare l'utente corrente dal database. Anche qui il problema è che ho bisogno di recuperare l'utente dal database per creare un record CallHistory (SalesRep = User).
Il codice nel mio repository fa 2 cose ora, 1, ha creato una voce di controllo per l'oggetto quando viene creato o aggiornato e, 2, ha anche creato una voce CallHistory ogni volta che il contatto viene aggiornato:
ContactRepository.SetCurrentUser(User).InsertOrUpdate(contact)
al fine di avere l'utente nel contesto Repository per:
var prop = typeof(T).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
if (prop.GetValue(entity, null).ToString() == "0")
{
// New entity
_context.Set<T>().Add(entity);
var auditLogger = entity as IAuditLogger;
if (auditLogger != null)
auditLogger.Audit = new Audit(true, _principal.Identity.Name);
}
else
{
// Existing entity
_context.Entry(entity).State = EntityState.Modified;
var auditLogger = entity as IAuditLogger;
if (auditLogger != null && auditLogger.Audit != null)
{
(entity as IAuditLogger).Audit.Updated = DateTime.Now;
(entity as IAuditLogger).Audit.UpdatedBy = _principal.Identity.Name;
}
var contact = entity as Contact;
if (_currentUser != null)
contact.CallHistories.Add(new CallHistory
{
CallTime = DateTime.Now,
Contact = contact,
Created = DateTime.Now,
CreatedBy = _currentUser.Logon,
SalesRep = _currentUser
});
}
}
c'è un modo per iniettare qualche modo l'utente di Windows in l'override SaveChanges nel DbContext e c'è anche un modo per andare a prendere un utente da il database basato su ID di accesso di Windows in modo da poter impostare il Sal esRep sul mio CallHistory (vedi sopra il codice)?
Qui è la mia azione sul controller MVC app:
[HttpPost]
public ActionResult Create([Bind(Prefix = "Contact")]Contact contact, FormCollection collection)
{
SetupVOs(collection, contact, true);
SetupBuyingProcesses(collection, contact, true);
var result = ContactRepository.Validate(contact);
Validate(result);
if (ModelState.IsValid)
{
ContactRepository.SetCurrentUser(User).InsertOrUpdate(contact);
ContactRepository.Save();
return RedirectToAction("Edit", "Contact", new {id = contact.Id});
}
var viewData = LoadContactControllerCreateViewModel(contact);
SetupPrefixDropdown(viewData, contact);
return View(viewData);
}
SamAccountName è modificabile quindi non è un buon identificatore. Io uso il guid della directory attiva che invece ottengono tutti gli oggetti – meffect