在模型中使用DateTime.UtcNow导致EF频繁生成迁移的问题咨询
问题解答
这确实是Entity Framework的预期行为,背后和它的实体状态追踪机制直接相关:
当你在种子数据中使用DateTime.UtcNow时,每次执行种子初始化操作(比如Update-Database或者自动运行种子逻辑),这个时间值都会重新计算。EF会将内存中新建的实体和数据库中已存在的实体进行字段对比,发现CreatedDateUtc和UpdatedDateUtc的数值和数据库里的不一致,就会标记这些字段为需要更新的状态,进而触发更新操作。
针对这个问题,你有两种可行的解决方案:
1. 使用固定的UTC日期值(推荐)
既然种子数据是用来初始化基础数据的,这些创建/更新日期通常不需要动态变化。直接使用固定的UTC日期,比如你示例中的写法:
new TestModel() { Id = 1, Name = name, CreatedDateUtc = new DateTime(2020, 01, 01, 12, 00, 00, DateTimeKind.Utc), CreatedBy = "Seed", UpdatedDateUtc = new DateTime(2020, 01, 01, 12, 00, 00, DateTimeKind.Utc), UpdatedBy = "Seed", DeletedDateUtc = null, DeletedBy = null };
这样每次种子运行时,实体的日期字段值都和数据库中存储的一致,EF就不会触发不必要的更新。
2. 手动设置实体状态为Unchanged
如果你确实需要在种子初始化时使用当前时间,也可以在添加/更新实体后,手动告诉EF不要追踪该实体的变化:
var testModel = new TestModel() { Id = 1, Name = name, CreatedDateUtc = DateTime.UtcNow, CreatedBy = "Seed", UpdatedDateUtc = DateTime.UtcNow, UpdatedBy = "Seed", DeletedDateUtc = null, DeletedBy = null }; context.TestModels.AddOrUpdate(t => t.Id, testModel); // 手动标记实体为未变更状态,避免EF触发更新 context.Entry(testModel).State = EntityState.Unchanged;
不过这种方法需要注意:如果后续你真的需要修改该实体的其他字段,可能需要额外处理状态追踪,所以固定日期的方案更适合种子数据的场景。
内容的提问来源于stack exchange,提问作者PiousVenom
相关产品推荐
相关产品推荐

