[英]Entity Framework 6.2.0 - DbContext that automatically saves which user created or updated a DbSet value
如标题所示,我们需要存储哪个用户更新或创建了特定值。 以前,我们只需要保存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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.