2011-10-03 7 views
21

UI, Business (entities) ve Data (DbContext) katmanlarına sahip bir ASP.NET MVC3 web uygulamasına sahibim. İlk önce Entity Framework 4.1 Kodunu kullanıyorum. Şu anda, DbContext.SaveChanges()'u Veri katmanında, IAuditable arabirimimi uygulayan herhangi bir varlık nesnesinde yapılan tüm değişiklikler için ModifiedDate'u ayarlayabileceğim şekilde geçersiz kılıyorum. sınıfına ve DateTime.Now döndüren bir yönteme (GetCurrentDate) sahibim (bir test çalıştırmıyorsam, bu durumda, ne söylediysem onu ​​döndürür).SaveChanges'i geçersiz kılma ve ModifiedDate'i ayarlama, ancak ModifiedBy'yi nasıl ayarlayabilirim?

ModifiedBy özelliğini otomatik olarak geçerli kullanıcıya da ayarlamak istiyorum. Bunu yapmanın en iyi yolu nedir? Bu bilgiye ulaşmamı sağlayacak ya da DateProvider sınıfına benzer bir şey ayarlamamı sağlayacak çerçevede yapılmış bir şey var mı? Bu bir Active Directory ortamıdır ve IIS'de WindowsAuthentication kullanıyoruz.

public override int SaveChanges() 
{ 
    var changeSet = ChangeTracker.Entries<IAuditable>(); 

    if (changeSet != null) 
    { 
     foreach (var entry in changeSet.Where(c => c.State != EntityState.Unchanged)) 
     { 
      entry.Entity.ModifiedDate = DateProvider.GetCurrentDate(); 
     } 
    } 
    return base.SaveChanges(); 
} 

cevap

37

Geçerli kullanıcının adını almak için HttpContext.Current.User.Identity.Name kullanabilirsiniz:

İşte benim SaveChanges kodudur. Bunu yapmak için

public override int SaveChanges() 
{ 
    var changeSet = ChangeTracker.Entries<IAuditable>(); 

    if (changeSet != null) 
    { 
     foreach (var entry in changeSet.Where(c => c.State != EntityState.Unchanged)) 
     { 
      entry.Entity.ModifiedDate = DateProvider.GetCurrentDate(); 
      entry.Entity.ModifiedBy = HttpContext.Current.User.Identity.Name; 
     } 
    } 
    return base.SaveChanges(); 
} 

yapIr Ben de MVC 4/Varlık Framework üzerinde denetim alanlarının nüfusu otomatik hale getirmek istedik

public class MyContext : DbContext 
{ 
    public MyContext(string userName) 
    { 
     UserName = userName; 
    } 

    public string UserName 
    { 
     get; private set; 
    } 

    public override int SaveChanges() 
    { 
     var changeSet = ChangeTracker.Entries<IAuditable>(); 

     if (changeSet != null) 
     { 
      foreach (var entry in changeSet.Where(c => c.State != EntityState.Unchanged)) 
      { 
       entry.Entity.ModifiedDate = DateProvider.GetCurrentDate(); 
       entry.Entity.ModifiedBy = UserName; 
      } 
     } 
     return base.SaveChanges(); 
    } 
} 
+0

Kurucu enjeksiyon yöntemini gerçekten çok seviyorum. Teşekkürler! – norepro

+0

Evet, harika fikir, yapıcı enjeksiyonu. – ProfK

10

bağlamına geçerli kullanıcıyı geçirmek için yapıcı enjeksiyon kullanmak olacaktır 5 uygulama. Ben Eranga cevabı @ bilgi ve bu blogu kullandı: Bu yaklaşım Ninject ile benim için iş yapmak için http://lourenco.co.za/blog/2013/07/audit-trails-concurrency-and-soft-deletion-with-entity-framework/ - değerli etmek durumunda ilanı herkesten:

public interface IAuditableEntity { 
    DateTime? CreatedDate { get; set; } 
    string CreatedBy { get; set; } 
    DateTime? LastModifiedDate { get; set; } 
    string LastModifiedBy { get; set; } 
} 

public abstract class AuditableEntity:IAuditableEntity { 
    public DateTime? CreatedDate { get; set; } 
    public string CreatedBy { get; set; } 
    public DateTime? LastModifiedDate { get; set; } 
    public string LastModifiedBy { get; set; } 
} 

onları Kullanılan:

bir arabirim ve soyut sınıf düzenlendi benim işletmelerdeki:

public class DataEntity : AuditableEntity { 
    public int DataEntityID { get; set; } 
    ... 
} 

eklendi HttpContext ve overrode SaveChanges kabul MyDbContext için bir yapıcı:

public EFDbContext(HttpContext context) { 
    _context = context; 
} 

public HttpContext _context { 
    get; 
    private set; 
} 

public override int SaveChanges() { 
    DateTime currentDateTime = DateTime.Now; 

    foreach (var auditableEntity in ChangeTracker.Entries<IAuditableEntity>()) { 
     if (auditableEntity.State == EntityState.Added || auditableEntity.State == EntityState.Modified) { 
      auditableEntity.Entity.LastModifiedDate = currentDateTime; 
      switch (auditableEntity.State) { 
        case EntityState.Added: 
         auditableEntity.Entity.CreatedDate = currentDateTime; 
         auditableEntity.Entity.CreatedBy = _context.User.Identity.Name; 
         break; 
        case EntityState.Modified: 
         auditableEntity.Entity.LastModifiedDate = currentDateTime; 
         auditableEntity.Entity.LastModifiedBy = _context.User.Identity.Name; 
         if (auditableEntity.Property(p => p.CreatedDate).IsModified || auditableEntity.Property(p => p.CreatedBy).IsModified) { 
          throw new DbEntityValidationException(string.Format("Attempt to change created audit trails on a modified {0}", auditableEntity.Entity.GetType().FullName)); 
         } 
         break; 
       } 
      } 
     } 
     return base.SaveChanges(); 
    } 

Son olarak - istek başına bir DbContext'iniz olması ve bu yanıtı temel alarak aşağıdaki gibi HttpContext'i iletmeniz gerekir: https://stackoverflow.com/a/3617961/1803682 - Şu anda MyDbContext kapsamı talep edildiğinde, Depoların da olması gerektiğini unutmayın.

kernel.Bind<IDataRepository>() 
     .To<EFDataRepository>() 
     .InRequestScope(); 

kernel.Bind<MyDbContext>().ToSelf() 
     .InRequestScope() 
     .WithConstructorArgument("context", ninjectContext=>HttpContext.Current); 
+0

Eranga'nın yanıtına ve bloguna bir göz atıyorum: http://lourenco.co.za/blog/2013/07/audit-trails-concurrency-and-soft-deletion-with-entity-framework/. Gördüğüm kadarıyla, veri değişikliklerini yeni bir tabloya kaydeder. Ancak, bu tabloda sadece birkaç sütun var ve tablo değerleri saklamıyor, yani hangi kayıt değişti, eski değer nedir, ya da hangi eylem denir? Peki, bunu nasıl başarabilirim? Eğer yanılıyorsam, lütfen açıklığa kavuşabilir misiniz? Şimdiden teşekkürler. –

+0

Tam cevap – lostmylogin