2015-06-27 41 views
4

我將使用UserName來跟蹤Created和Modified字段。要做到這一點我已引用System.Web程序集裏面直接的DbContext:訪問DbContext中的HttpContext.Current.User.Identity.Name

public void auditFields() 
{ 
      var auditDate = DateTime.Now; 
      foreach (var entry in this.ChangeTracker.Entries<BaseEntity>()) 
      { 
       switch (entry.State) 
       { 
        case EntityState.Detached: 
         break; 
        case EntityState.Unchanged: 
         break; 
        case EntityState.Added: 
         entry.Entity.CreatedOn = auditDate; 
         entry.Entity.ModifiedOn = auditDate; 
         entry.Entity.CreatedBy = HttpContext.Current.User.Identity.Name ?? "anonymouse"; 
         entry.Entity.ModifiedBy = HttpContext.Current.User.Identity.Name ?? "anonymouse"; 
         break; 
        case EntityState.Deleted: 
         break; 
        case EntityState.Modified: 
         entry.Entity.ModifiedOn = auditDate; 
         entry.Entity.ModifiedBy = HttpContext.Current.User.Identity.Name ?? "anonymouse"; 
         break; 
        default: 
         throw new ArgumentOutOfRangeException(); 
       } 
      } 
} 

它的工作原理,但它緊密地與HttpContext的這是不是在情況下是個好主意,我們將暴露的DbContext到耦合的DbContext非網絡環境。 所以我用這樣的方式:

public class ApplicationDbContext : 
     IdentityDbContext<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUserClaim>, 
     IUnitOfWork 
{ 
    public ApplicationDbContext() 
      : base("ConnectionString") 
     { 
     } 
     public ApplicationDbContext(string userName) 
      : base("ConnectionString") 
     { 
      UserName = userName; 
     } 
    //Other codes 
    public string UserName 
     { 
      get; 
      private set; 
     } 
    public void auditFields() 
    { 
      var auditDate = DateTime.Now; 
      foreach (var entry in this.ChangeTracker.Entries<BaseEntity>()) 
      { 
       switch (entry.State) 
       { 
        case EntityState.Detached: 
         break; 
        case EntityState.Unchanged: 
         break; 
        case EntityState.Added: 
         entry.Entity.CreatedOn = auditDate; 
         entry.Entity.ModifiedOn = auditDate; 
         entry.Entity.CreatedBy = UserName ?? "anonymouse"; 
         entry.Entity.ModifiedBy = UserName ?? "anonymouse"; 
         break; 
        case EntityState.Deleted: 
         break; 
        case EntityState.Modified: 
         entry.Entity.ModifiedOn = auditDate; 
         entry.Entity.ModifiedBy = UserName ?? "anonymouse"; 
         break; 
        default: 
         throw new ArgumentOutOfRangeException(); 
       } 
      } 
    } 
} 

而且在國際奧委會的配置項目(我在其他類庫使用structureMap):

ioc.For<IUnitOfWork>() 
        .HybridHttpOrThreadLocalScoped() 
        .Use<ApplicationDbContext>() 
        .Ctor<string>().Is(HttpContext.Current.User.Identity.Name); 

但是當我運行應用程序,我會得到這個上述錯誤:

Object reference not set to an instance of an object 

看來它不能注入HttpContext。

有什麼想法?

+0

「ThreadLocalScoped」 聽起來可疑...... - 我不知道如何與你的一生容器的交易,但HttpContext的。當前有效的請求僅限於線程處理請求,並且很可能您的對象在不同的​​時間被解析。 –

+1

這對於[Pure DI](http://blog.ploeh.dk/2014/06/10/pure-di)來說簡單得多,更不用說類型安全了。 –

+1

典型案例:以下是我在Castle Windsor做類似事情時遇到的麻煩:http://stackoverflow.com/q/10854701/126014 –

回答

2

看看這個鏈接http://techbrij.com/service-layer-entity-framework-asp-net-mvc-unit-testing

筆者的解決方案看起來像你(但他用AutoFac代替StructureMap)。他的「伎倆」獲得「名稱」是Thread.CurrentPrincipal.Identity.Name;

另一件事,恕我直言,我認爲你應該使用DateTimeOffSet而不是DateTime審計日期。使用DateTimeOffSet您將不會遇到不同時區的問題。就像這樣:

DateTimeOffSet auditDate = DateTime.UtcNow; 
相關問題