正如标题所述,我们需要存储哪个用户更新或创建了特定值。以前,我们只需要保存CreatedDate
和UpdatedDate
。这很容易,我们所有的实体都继承自抽象基类
名为EntityBase
的示例,它实现了具有这些值的接口IEntity
。然后DbContext
SaveChanges
被覆盖,如果实现了特定实体IEntity
,则根据EntityState.Added
或EntityState.Modified
设置值。
interface IEntity
{
DateTime CreatedDate { get; set; }
string CreatedBy { get; set; }
DateTime UpdatedDate { get; set; }
string UpdatedBy { get; set; }
}
public abstract class EntityBase<T1>: IEntity
{
public T1 Id { get; set; }
public virtual DateTime CreatedDate { get; set; }
public virtual string CreatedBy { get; set; }
public virtual DateTime UpdatedDate { get; set; }
public virtual string UpdatedBy { get; set; }
}
但是,新的要求是我们还需要保存哪个用户进行了更改。一个简单的解决方案是通过构造函数添加用户,而没有一个空的构造函数。但是,在其他环境中使用迁移时,这证明是一个问题:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<CatalogServiceContext, Configuration>());
var migrator = new DbMigrator(new Configuration());
目标上下文'CatalogService.Data.Context.CatalogServiceContext' 是不可建设的。添加默认构造函数或提供一个 IDbContextFactory的实现。
public class CatalogServiceContext : DbContext
{
private readonly string _currentUser;
public CatalogServiceContext(string currentUser) : base("name=CatalogContext")
{
_currentUser = currentUser;
}
public override int SaveChanges()
{
var now = DateTime.Now;
foreach (var changedEntity in ChangeTracker.Entries())
{
if (changedEntity.Entity is IEntity entity)
{
switch (changedEntity.State)
{
case EntityState.Added:
entity.CreatedDate = now;
entity.CreatedBy = _currentUser;
entity.UpdatedDate = now;
entity.UpdatedBy = _currentUser;
break;
case EntityState.Modified:
Entry(entity).Property(x => x.CreatedDate).IsModified = false;
Entry(entity).Property(x => x.CreatedBy).IsModified = false;
entity.UpdatedDate = now;
entity.UpdatedBy = _currentUser;
break;
}
}
}
return base.SaveChanges();
}
}
我尝试实现IDbContextFactory
,但是它也有类似的问题。
上下文工厂类型 'CatalogService.Data.Context.CatalogServiceContextFactory'不 有一个公共的无参数构造函数。要么添加一个公共 无参数构造函数,创建一个IDbContextFactory实现 在上下文程序集中,或者使用以下命令注册上下文工厂 DbConfiguration。
public class CatalogServiceContextFactory : IDbContextFactory<CatalogServiceContext>
{
private readonly string _currentUser;
public CatalogServiceContextFactory(string currentUser)
{
_currentUser = currentUser;
}
public CatalogServiceContext Create()
{
return new CatalogServiceContext(_currentUser);
}
}
一种解决方法是EntityBase
中的两个方法,每次更新或创建值时都需要调用它们。这可行,但是我认为最好的解决方案仍然是构造函数中的强制用户。还有其他人有类似的需求可以解决吗?我想在DbContext
中解决它,而不要对每个DbSet
使用一个存储库抽象。
public virtual EntityBase<T1> SetCreateFields(string currentUser)
{
CreatedBy = currentUser;
UpdatedBy = currentUser;
return this;
}
public virtual EntityBase<T1> SetUpdateFields(string currentUser)
{
UpdatedBy = currentUser;
return this;
}
答案 0 :(得分:0)
决定像这样解决它:
public class CatalogServiceContext : DbContext
{
public ICurrentUser CurrentUser;
[Obsolete("Use CatalogServiceContextUserWrapper instead")]
public CatalogServiceContext() : base("name=CatalogContext")
{
}
...
public class CatalogServiceContextUserWrapper
{
public CatalogServiceContext Context;
public CatalogServiceContextUserWrapper(CatalogServiceContext context, ICurrentUser currentUser)
{
context.CurrentUser = currentUser;
this.Context = context;
}
}