ef6 中的自动 CreatedAt 和 UpdatedAt 字段 OnModelCreating()

问题描述 投票:0回答:4

我的

CreatedAt
模型中有
UpdatedAt
User
列。

User.cs

public string Name { get; set; }
public DateTime? CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }

要求

  • 当我们
    SaveChanges()
    用户记录时,
    CreatedAt
    UpdatedAt
    应该自动保存,例如:
    DateTime.UtcNow
  • 当我更新
    User
    记录时,只有
    UpdatedAt
    列应更新为当前日期时间。
  • 对于所有其他型号,这应该自动发生,可能是
    OnModelCreating()
    中的某些配置。
  • 我希望这种行为能够从数据库以及其他地方找到
    latest
    记录。
  • 我正在使用
    code first
    迁移方法
  • 我正在使用MySQL服务器,
    MySql.Data
    MySql.Data.Entity.EF6

更新

我添加了

BaseEntity.cs
模型

public abstract class BaseEntity
    {
        public DateTime CreatedAt { get; set; }
        public DateTime UpdatedAt { get; set; }
    }

从BaseEntity继承User

public class User : BaseEntity
{
  public int Id { get; set; }
  public int FullName { get; set; }
}

并更新了迁移以包括

defaultValueSql()

AddColumn("dbo.Users", "CreatedAt", c => c.DateTime(nullable: false, precision: 0, defaultValueSql: "NOW()"));
AddColumn("dbo.Users", "UpdatedAt", c => c.DateTime(nullable: false, precision: 0, defaultValueSql: "NOW()"));"

现在,需要一种方法来修复每次更新中的

UpdatedAt
列。

c# asp.net-mvc-5 entity-framework-6
4个回答
23
投票

终于找到了我的问题的解决方案。因为我们可以将数据库从

MySql
更改为
postgresql
Ms Sql server
,所以使用 sql 查询添加默认值似乎不是正确的解决方案。

这是我解决问题的方法。

添加

Base
型号

 public abstract class BaseEntity
 {
    public DateTime? CreatedAt { get; set; }
    public DateTime? UpdatedAt { get; set; }
 }

从这个基础模型继承你的所有模型,在我的例子中它是

User

public class User : BaseEntity
{
  public int Id { get; set; }
  public int FullName { get; set; }
}

如果您使用代码优先方法,请不要忘记生成迁移。迁移应该足够简单:

示例:

AddColumn("dbo.Users", "CreatedAt", c => c.DateTime(precision: 0));
AddColumn("dbo.Users", "UpdatedAt", c => c.DateTime(precision: 0));

最后一步是在您的上下文中覆盖

SaveChanges()
SaveChangesAsync()

public class MyDbContext : DbContext
{
    public DbSet<User> Users { get; set; }

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

    public override async Task<int> SaveChangesAsync()
    {
        AddTimestamps();
        return await base.SaveChangesAsync();
    }

    private void AddTimestamps()
    {
        var entities = ChangeTracker.Entries()
            .Where(x => x.Entity is BaseEntity && (x.State == EntityState.Added || x.State == EntityState.Modified));

        foreach (var entity in entities)
        {
            var now = DateTime.UtcNow; // current datetime

            if (entity.State == EntityState.Added)
            {
                ((BaseEntity)entity.Entity).CreatedAt = now;
            }
            ((BaseEntity)entity.Entity).UpdatedAt = now;
        }
    }
}

3
投票

我看到了@przbadu 的帖子,我有点困难。 我正在使用 dotnet core 2.2,我的覆盖需要将 SaveChangeAsync 方法更改为:

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

public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
    AddTimestamps();
    return base.SaveChangesAsync();
}

private void AddTimestamps()
{
    var entities = ChangeTracker.Entries()
        .Where(x => x.Entity is BaseEntity && (x.State == EntityState.Added || x.State == EntityState.Modified));

    foreach (var entity in entities)
    {
        var now = DateTime.UtcNow; // current datetime

        if (entity.State == EntityState.Added)
        {
            ((BaseEntity)entity.Entity).CreatedAt = now;
        }
        ((BaseEntity)entity.Entity).UpdatedAt = now;
    }
}

1
投票

您可以像这样定义自己:


interface

现在让你想要的每个模型实现这个接口。
然后给自己写一个
public interface ITiming { DateTime CreatedAt {get; set; } DateTime UpdatedAt {get; set; } }

,如下所示:


ExtionsionMethod



0
投票

public static SaveChangesTimed(this YourDbContext _context, ITiming timed) { timed.CreatedAt = DateTime.Now; timed.UpdatedAt = Datetime.Now; _context.SaveChanges(); }

应用后会生成 mysql 代码:

更改表..修改列

protected override void OnModelCreating(ModelBuilder modelBuilder) { foreach (var entityType in modelBuilder.Model.GetEntityTypes()) { entityType.FindProperty("updatedAt")?.SetDefaultValueSql("CURRENT_TIMESTAMP(6)"); entityType.FindProperty("createdAt")?.SetDefaultValueSql("CURRENT_TIMESTAMP(6)"); modelBuilder.Entity(entityType.Name).Property("updatedAt").ValueGeneratedOnAddOrUpdate(); } }

日期时间(6)更新CURRENT_TIMESTAMP(6)时为空默认CURRENT_TIMESTAMP(6);

    

© www.soinside.com 2019 - 2024. All rights reserved.