实体框架6.2.0-DbContext,自动保存哪个用户创建或更新了DbSet值



正如标题所说,我们需要存储更新或创建特定值的用户。以前我们只需要保存CreatedDateUpdatedDate。这很容易,我们让所有实体都继承自一个抽象基类称为CCD_ 3,其实现具有这些值的接口CCD_。DbContextSaveChanges随后被覆盖,并且如果特定实体实现IEntity,则基于EntityState.AddedEntityState.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"是不可构造的。添加默认构造函数或提供IDbContentFactory的实现。

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"不有一个公共的无参数构造函数。要么添加公共无参数构造函数,创建IDbContentFactory实现在上下文程序集中,或使用注册上下文工厂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;
}
}

最新更新