2015-06-27 40 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; 
相关问题