在代码优先方法中,如何定义实体以便: CreatedOn
not null—db在插入时使用当前时间戳生成值 Updated
空值由db使用当前时间戳更新时生成
示例实体:
public class MyEntity
{
public int Id { get; set; }
public string Name { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column(TypeName = "TIMESTAMP")]
public DateTime CreatedOn { get; set; }
[Column(TypeName = "TIMESTAMP")]
public DateTime UpdatedOn { get; set; }
}
数据库上下文:
public class MyContext : DbContext
{
public MyContext(DbContextOptions options) : base(options) {}
public DbSet<MyEntity> Entities { get; set; }
}
数据库的最终结果应该是: CreatedOn
not null-没有额外的-默认值可以是当前的\u时间戳 UpdatedOn
null-额外更新当前\u时间戳-无默认值或默认值为null
1条答案
按热度按时间0s7z1bwu1#
问题:
我把范围缩小到(看起来)柚子里的虫子。问题在于:
https://github.com/pomelofoundation/pomelo.entityframeworkcore.mysql/issues/801
问题是,柚子创造了一个
defaultValue
的属性DateTime
以及生成迁移时的其他结构。如果在迁移中设置了一个默认值,那么它将覆盖值生成策略,并且sql看起来不正确。解决方法是生成迁移,然后手动修改迁移文件以设置
defaultValue
至null
(或删除整个行)。例如,更改以下内容:
对此:
然后,迁移脚本将使用
DEFAULT CURRENT_TIMESTAMP
为了TIMESTAMP
. 如果你移除[Column(TypeName = "TIMESTAMP")]
属性,它将使用datetime(6)
列和吐出来DEFAULT CURRENT_TIMESTAMP(6)
.解决方案:
我提出了一个解决方法,可以正确地实现created time(仅在insert时由数据库更新)和updated time(仅在insert和update时由数据库更新)。
首先,定义实体如下:
然后,将以下内容添加到
OnModelCreating()
:这将产生一个完美的初始迁移(其中
migrationBuilder.CreateTable
,并生成预期的sql:这也适用于更新现有表的迁移,但请确保
defaultValue
始终为空。这个
SetBeforeSaveBehavior
以及SetAfterSaveBehavior
行阻止ef尝试用默认值覆盖创建的时间。它有效地使创建和更新的列从ef的Angular 来看是只读的,从而允许数据库完成所有的工作。您甚至可以将其提取到接口和扩展方法中:
然后在所有带时间戳的实体上实现接口:
这允许您从内部设置实体
OnModelCreating()
像这样: