我正在尝试使用EF迁移来构建/播种我的数据库,但是当我使用update-database命令时,我的DbContext导致错误。
我实现的DbContext有两个构造函数:一个不接受参数,另一个接受IUserContext接口。 IUserContext接口返回用户名作为字符串。 IUserContext用于SaveChanges()方法,用于设置我所有实体共有的用户相关审计字段(例如CreatedBy,UpdatedBy)。根据IUserContext接口的实现,可以从HttpContext(在mvc应用程序中),WindowsIdentity(在控制台应用程序中)等中检索用户名。
如果用户尝试在DbContext上调用SaveChanges并且未设置IUserContext,则会抛出异常。基本上, 如果IUserContext接口无法提供用户名以便记录谁正在进行修改,我不希望保存在DbContext中的更改。 如果DbContext正在仅用于查询,使用no-args构造函数不是问题,因为IUserContext仅在SaveChanges期间使用。
当我尝试使用update-database命令时,DbMigrationsConfiguration被赋予一个使用no-args构造函数实例化的DbContext实例。因此,当它尝试在Seed()方法之后调用DbContext的SaveChanges时抛出异常。
问题: 如何将IUserContext传递给我的DbContext,这样update-database命令不会失败,更重要的是,能够将相应的实体字段设置为播种用户名的用户名更改? 我可以在DbMigrationsConfiguration中执行某种形式的DI或其他自定义吗?我应该简单地向DbContext添加一个IUserContext访问器方法,以便可以在构造函数之外设置IUserContext吗?
也许我应该问一个更大的问题: 将用户信息转发到DbContext的最佳(最通用?)方式是什么,以便记录谁在制作修改 ?
我考虑过将这个逻辑移到我的应用程序的业务层,但将它封装在DbContext的SaveChanges中似乎很方便(更改跟踪时更是如此)已启用)。
答案 0 :(得分:0)
我们有类似的情况,我们在SaveChanges()覆盖中记录修改后的用户。我们最终做的是创建一个BaseWrapper并使用IoC来填充它。第二部分是创建迁移将用于创建上下文的MigrationsContextFactory。该类与ApplicationDbContext位于同一文件夹中。
using System.Data.Entity.Infrastructure;
namespace MyApp.Data
{
public class MigrationsContextFactory : IDbContextFactory<ApplicationDbContext>
{
public ApplicationDbContext Create()
{
return new ApplicationDbContext(new HttpContextBaseWrapper());
}
}
}
public class HttpContextBaseWrapper : IHttpContextBaseWrapper
{
public string UserName
{
get
{
if (HttpContext.Current == null || HttpContext.Current.User == null)
return string.Empty;
return HttpContext.Current.User.Identity.Name;
}
}
}