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

时间:2018-12-28 15:13:25

标签: c# entity-framework

正如标题所述,我们需要存储哪个用户更新或创建了特定值。以前,我们只需要保存CreatedDateUpdatedDate。这很容易,我们所有的实体都继承自抽象基类  名为EntityBase的示例,它实现了具有这些值的接口IEntity。然后DbContext SaveChanges被覆盖,如果实现了特定实体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'   是不可建设的。添加默认构造函数或提供一个   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;
}

1 个答案:

答案 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;
    }
}