【问题标题】:DbContext.SaveChanges overrides behaves unexpectedDbContext.SaveChanges 覆盖行为意外
【发布时间】:2021-08-01 16:54:58
【问题描述】:

我有一个 EFCore、.NET5 应用程序。我的大多数模型都使用基类:

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);
}

我想实现 CreatedOnCreatedBy 仅在插入时更新。但它们也会随着更新而更新。

这看起来不错:

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

如果没有CreatedByCreatedOn,我会期待更新声明:

UPDATE [Organization] SET [Description] = @p2, [Name] = @p5, [UpdatedBy] = @p6, [UpdatedOn] = @p7, [UserProfileId] = @p8

现在,这些属性会被默认值覆盖。

我查看了许多示例,并且整天都在尝试不同的选项,但我看不出我做错了什么。请指教。

我在获取 UserProfileId 时也遇到了问题,但我会为此创建一个新问题。

【问题讨论】:

标签: asp.net-core entity-framework-core dbcontext


【解决方案1】:

感谢@IvanStoev 的建议,我终于找到了可行的解决方案。

我加了

if (entityEntry.State == EntityState.Modified)
{
    entityEntry.Property("CreatedOn").IsModified = false;
    entityEntry.Property("CreatedBy").IsModified = false;
}

到我的SaveChangesAsync() 并删除了我的配置中的ValueGenerated* 属性并删除了我的基本模型中的[DatabaseGenerated(DatabaseGeneratedOption.Identity)] 属性。

【讨论】:

    猜你喜欢
    • 2016-09-16
    • 1970-01-01
    • 2020-05-09
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    • 1970-01-01
    • 1970-01-01
    • 2015-12-24
    相关资源
    最近更新 更多