正如标题所说,我们需要存储哪些用户更新或创建一个特定的值。以前我们只需要保存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;
}
决定解决这个问题是这样的:
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;
}
}