DbContext.SaveChanges 覆盖行为异常
DbContext.SaveChanges overrides behaves unexpected
我有一个 EFCore、.NET5 应用程序。我的大多数模型都使用基数 class:
public class BaseModel
{
[Key]
public int Id { get; set; }
[MaxLength(512), Required]
public string Name { get; set; }
[StringLength(8192)]
public string Description { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public DateTime CreatedOn { get; set; } = DateTime.UtcNow;
[DatabaseGenerated(DatabaseGeneratedOption.Identity), Required]
public string CreatedBy { get; set; } = "Admin";
[Required]
public DateTime UpdatedOn { get; set; } = DateTime.UtcNow;
[Required]
public string UpdatedBy { get; set; } = "Admin";
}
我还有一个配置文件:
public virtual void Configure(EntityTypeBuilder<TEntity> builder)
{
builder.Property(b => b.CreatedOn).HasDefaultValueSql("GETUTCDATE()").ValueGeneratedNever();
builder.Property(b => b.CreatedBy).HasDefaultValue("External").ValueGeneratedOnAdd();
builder.Property(b => b.UpdatedOn).HasDefaultValueSql("GETUTCDATE()");
builder.Property(b => b.UpdatedBy).HasDefaultValue("External");
}
我覆盖 SaveChangesAsync()
方法以尝试自动添加和更新 Created 和 Updated 属性:
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new())
{
var entries = ChangeTracker
.Entries()
.Where(e => e.Entity is BaseModel &&
e.State is EntityState.Added or EntityState.Modified);
foreach (var entityEntry in entries)
{
if (entityEntry.State is EntityState.Detached or EntityState.Unchanged) continue;
((BaseModel)entityEntry.Entity).UpdatedOn = DateTime.UtcNow;
((BaseModel) entityEntry.Entity).UpdatedBy = _userId;
if (entityEntry.State == EntityState.Added)
{
((BaseModel)entityEntry.Entity).CreatedOn = DateTime.UtcNow;
((BaseModel) entityEntry.Entity).CreatedBy = _userId;
}
}
return base.SaveChangesAsync(cancellationToken);
}
我想实现 CreatedOn
和 CreatedBy
仅在插入时更新。但它们也会在更新时更新。
这看起来不错:
INSERT INTO [Organization] ([CreatedBy], [CreatedOn], [Description], [Name], [UpdatedBy], [UpdatedOn], [UserProfileId])
这不是:
UPDATE [Organization] SET [CreatedBy] = @p0, [CreatedOn] = @p1, [Description] = @p2, [Name] = @p5, [UpdatedBy] = @p6, [UpdatedOn] = @p7, [UserProfileId] = @p8
我希望更新语句没有 CreatedBy
和 CreatedOn
:
UPDATE [Organization] SET [Description] = @p2, [Name] = @p5, [UpdatedBy] = @p6, [UpdatedOn] = @p7, [UserProfileId] = @p8
现在,这些属性被默认值覆盖。
我看了很多例子,一整天都在尝试不同的选择,但我看不出我做错了什么。请指教
我也有获取 UserProfileId 的问题,但我会为此创建一个新问题。
感谢@IvanStoev 的建议,我终于找到了可行的解决方案。
我加了
if (entityEntry.State == EntityState.Modified)
{
entityEntry.Property("CreatedOn").IsModified = false;
entityEntry.Property("CreatedBy").IsModified = false;
}
到我的 SaveChangesAsync()
并删除了我的配置中的 ValueGenerated*
属性并删除了我的基本模型中的 [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
属性。
我有一个 EFCore、.NET5 应用程序。我的大多数模型都使用基数 class:
public class BaseModel
{
[Key]
public int Id { get; set; }
[MaxLength(512), Required]
public string Name { get; set; }
[StringLength(8192)]
public string Description { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public DateTime CreatedOn { get; set; } = DateTime.UtcNow;
[DatabaseGenerated(DatabaseGeneratedOption.Identity), Required]
public string CreatedBy { get; set; } = "Admin";
[Required]
public DateTime UpdatedOn { get; set; } = DateTime.UtcNow;
[Required]
public string UpdatedBy { get; set; } = "Admin";
}
我还有一个配置文件:
public virtual void Configure(EntityTypeBuilder<TEntity> builder)
{
builder.Property(b => b.CreatedOn).HasDefaultValueSql("GETUTCDATE()").ValueGeneratedNever();
builder.Property(b => b.CreatedBy).HasDefaultValue("External").ValueGeneratedOnAdd();
builder.Property(b => b.UpdatedOn).HasDefaultValueSql("GETUTCDATE()");
builder.Property(b => b.UpdatedBy).HasDefaultValue("External");
}
我覆盖 SaveChangesAsync()
方法以尝试自动添加和更新 Created 和 Updated 属性:
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new())
{
var entries = ChangeTracker
.Entries()
.Where(e => e.Entity is BaseModel &&
e.State is EntityState.Added or EntityState.Modified);
foreach (var entityEntry in entries)
{
if (entityEntry.State is EntityState.Detached or EntityState.Unchanged) continue;
((BaseModel)entityEntry.Entity).UpdatedOn = DateTime.UtcNow;
((BaseModel) entityEntry.Entity).UpdatedBy = _userId;
if (entityEntry.State == EntityState.Added)
{
((BaseModel)entityEntry.Entity).CreatedOn = DateTime.UtcNow;
((BaseModel) entityEntry.Entity).CreatedBy = _userId;
}
}
return base.SaveChangesAsync(cancellationToken);
}
我想实现 CreatedOn
和 CreatedBy
仅在插入时更新。但它们也会在更新时更新。
这看起来不错:
INSERT INTO [Organization] ([CreatedBy], [CreatedOn], [Description], [Name], [UpdatedBy], [UpdatedOn], [UserProfileId])
这不是:
UPDATE [Organization] SET [CreatedBy] = @p0, [CreatedOn] = @p1, [Description] = @p2, [Name] = @p5, [UpdatedBy] = @p6, [UpdatedOn] = @p7, [UserProfileId] = @p8
我希望更新语句没有 CreatedBy
和 CreatedOn
:
UPDATE [Organization] SET [Description] = @p2, [Name] = @p5, [UpdatedBy] = @p6, [UpdatedOn] = @p7, [UserProfileId] = @p8
现在,这些属性被默认值覆盖。
我看了很多例子,一整天都在尝试不同的选择,但我看不出我做错了什么。请指教
我也有获取 UserProfileId 的问题,但我会为此创建一个新问题。
感谢@IvanStoev 的建议,我终于找到了可行的解决方案。
我加了
if (entityEntry.State == EntityState.Modified)
{
entityEntry.Property("CreatedOn").IsModified = false;
entityEntry.Property("CreatedBy").IsModified = false;
}
到我的 SaveChangesAsync()
并删除了我的配置中的 ValueGenerated*
属性并删除了我的基本模型中的 [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
属性。