我正在建立一个MVC 5,WebApi 2,实体框架解决方案。我想在我的数据库中插入审计字段,而不是每次都编写样板代码来执行此操作。我的数据库实体位于他们自己的独立项目中,该项目引用了EntityFramework。
到目前为止,我有:
public class MyDbContext : IdentityDbContext<ApplicationUser>
{
public MyDbContext(/*Autofac can inject stuff here*/)
{
}
public override int SaveChanges()
{
// Updates ModifiedBy, CreatedBy, ModifiedOn, CreatedOn fields
DbContextHelper.TrackSaveChanges(ChangeTracker, userName);
return base.SaveChanges();
}
}
TrackSaveChanges()
内的逻辑并不重要,这只是循环遍历所有已更改的实体并在字段上设置值。没什么太聪明的。
问题是在我的userName
派生类中获得DbContext
。我想最好的方法是在MyDbContext
构造函数上注入它?
有关使用HttpContext.Current.User
的建议,但我不想在我的数据项目中添加Web依赖项。此外,对HttpContext
的直接引用也会影响单位可测试性。
builder.Register<IPrincipal>(ip => HttpContext.Current.User);
中尝试将IPrincipal
注入dbcontext,但由于HttpContext.Current.User在创建时为null,因此会引发异常。 HttpContextBase
代替HttpContext
。有干净的方法吗? 我正在使用Entity Framework 6,WebAPI 2,ASP NET Identity和Autofac。
答案 0 :(得分:4)
您可以注入接口而不是string
值本身:
interface IUserNameProvider
{
string GetUserName();
}
具体实现将使用HttpContext.Current.User
,但这种方法不会影响可测试性,因为界面很容易被模拟。
interface HttpContextUserNameProvider : IUserNameProvider
{
public string GetUserName()
{
return HttpContext.Current.User;
}
}
客户端代码示例:
public class MyDbContext : IdentityDbContext<ApplicationUser>
{
internal IUserNameProvider _userNameProvider;
public MyDbContext(IUserNameProvider userNameProvider)
{
_userNameProvider = userNameProvider;
}
public override int SaveChanges()
{
string userName = _userNameProvider.GetUserName();
// ...
}
}