Entity Framework 核心 - 通常先在代码中为公共列分配动态值

Entity Framework Core - Generically assign dynamic values to common columns in code first

我正在尝试在一个地方使用代码为所有表中的公共列分配值。我的场景如下。

我在所有表中都有公共列,例如 "CreatedBy"、"CompanyId",它们派生自 BaseEntity。

public abstract class BaseEntity
    {
        public DateTime? CreatedDateTime { get; set; }

        public DateTime? ModifiedDateTime { get; set; }

        public int? CreatedBy { get; set; }

        public int CompanyId { get; set; }

        public int? ModifiedBy { get; set; }
    }

像 "CompanyId" 这样的值只能在 运行 时设置,不能使用 SQL 服务器默认值。当我在存储库中添加实体时手动分配此值时,如果有任何子实体将包含空值,直到我手动分配它们为止。我正在寻找一个通用的解决方案,这样我就不必在每个位置一次又一次地分配这些列。

要设置所有表中的所有公共列,请重写 DbContext 的 SaveChanges 和 SaveChangesAsync 方法,如下所示。

public class MyContext : DbContext
    {
        public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
        {
            SetBaseValues();
            return base.SaveChangesAsync(cancellationToken);
        }

        public override int SaveChanges()
        {
            SetBaseValues();
            return base.SaveChanges();
        }

        private void SetBaseValues()
        {
            var addedEntries = ChangeTracker.Entries().Where(e => e.State == EntityState.Added);
            var utcNow = DateTime.UtcNow;
            foreach (var entry in addedEntries)
            {
                entry.Property("CreatedDateTime").CurrentValue = utcNow;
                entry.Property("CreatedBy").CurrentValue = UserData.GetCurrentUserId();
            }
            var modifiedEntries = ChangeTracker.Entries().Where(e => e.State == EntityState.Modified);
            foreach (var entry in modifiedEntries)
            {
                entry.Property("CreatedDateTime").IsModified = false;
                entry.Property("CreatedBy").IsModified = false;
                entry.Property("ModifiedDateTime").CurrentValue = utcNow;
                entry.Property("ModifiedBy").CurrentValue = UserData.GetCurrentUserId();
            }
        }
    }

在这里,"UserData" 是 class 负责您的会话数据,例如当前登录的用户、当前用户的公司 ID 等,或者您可以将其替换为应用程序中的任何其他相关代码. 此解决方案将 运行 适用于每个场景,也适用于 nested/child 实体。而且,您无需在应用程序的任何地方再次分配这些值。