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 实体。而且,您无需在应用程序的任何地方再次分配这些值。
我正在尝试在一个地方使用代码为所有表中的公共列分配值。我的场景如下。
我在所有表中都有公共列,例如 "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 实体。而且,您无需在应用程序的任何地方再次分配这些值。