我的
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.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
列。
终于找到了我的问题的解决方案。因为我们可以将数据库从
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;
}
}
}
我看到了@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;
}
}
您可以像这样定义自己:
interface
现在让你想要的每个模型实现这个接口。 然后给自己写一个
public interface ITiming {
DateTime CreatedAt {get; set; }
DateTime UpdatedAt {get; set; }
}
,如下所示:
ExtionsionMethod
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);