在模型上使用 DateTime.UtcNow 总是在实体中创建迁移

Using DateTime.UtcNow on model always creates a migration in Entity

我有几个模型有创建日期 and/or 更新日期 属性,在我的播种中我将它们设置为 DateTime.UtcNow。

new TestModel()
{
    Id = 1,
    Name = name,
    CreatedDateUtc = DateTime.UtcNow,
    CreatedBy = "Seed",
    UpdatedDateUtc = DateTime.UtcNow,
    UpdatedBy = "Seed",
    DeletedDateUtc = null,
    DeletedBy = null,
},

现在,即使种子数据在数据库中,EF 认为它需要用新日期更新它们。这是预期的行为吗?我是否坚持为这些专栏指定日期?像这样:

DateTime(2020, 01, 01, 12, 00, 00, DateTimeKind.Utc)

使用 HasData 播种,EF 每次都会将日期解析为新日期。

如果我是你,我会使用谓词table 和具有固定日期的可重现种子。

或者如果您真的需要使用 Now,您可以尝试 manual migration 并事先检查您的 table 种子是否已经 运行 具有一些自定义逻辑。

每次种子方法为 运行ning 时,它都会覆盖所有列,并且每次日期都不同。如果你想防止这种覆盖输入数据,那么你需要检查它是否已经存在于你的数据库中然后 运行 它。或者覆盖 DbContext 中的 SaveChanges() 方法,如果想防止更新某些字段。

例子:-

1.If 那你不想更新输入数据--

protected override void Seed(ApplicationDbContext context)
{
    if (!context.TestModels.Any(u => u.Id== 1))
    {
          context.TestModels.AddOrUpdate(p => p.Id, new TestModel()
            {
                Id = 1,
                Name = "Test",
                CreatedDateUtc = DateTime.UtcNow,
                CreatedBy = "Seed",
                UpdatedDateUtc = DateTime.UtcNow,
                UpdatedBy = "Seed",
                DeletedDateUtc = null,
                DeletedBy = null,
            });
    }
 base.Seed(context);
}

2.If 想要防止更新某些字段(此过程适用于当前 DbContext 中任何位置的任何实体)--

属性--

[AttributeUsage(AttributeTargets.All, AllowMultiple = false)]
public sealed class IgnoreUpdateAttribute : Attribute
{
}

型号--

public class TestModel
{

    public int Id { get; set; }
    public string Name { get; set; }
    [IgnoreUpdate]//for ignoring update
    public DateTime CreatedDateUtc { get; set; }
    [IgnoreUpdate]//for ignoring update
    public string CreatedBy { get; set; }
    public DateTime UpdatedDateUtc { get; set; }
    public string UpdatedBy { get; set; }
    public DateTime? DeletedDateUtc { get; set; }
    public string DeletedBy { get; set; }
}

种子--

    protected override void Seed(ApplicationDbContext context)
    {

        context.TestModels.AddOrUpdate(p => p.Id, new TestModel()
        {
            Id = 1,
            Name = "Test",
            CreatedDateUtc = DateTime.UtcNow,
            CreatedBy = "Seed",
            UpdatedDateUtc = DateTime.UtcNow,
            UpdatedBy = "Seed",
            DeletedDateUtc = null,
            DeletedBy = null,
        });

        base.Seed(context);
    }

DbContext--

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
        }
        public DbSet<TestModel> TestModels { get; set; }
//---DB Set
        public override int SaveChanges()
        {
           var entities= ChangeTracker.Entries().Where(e => e.State == EntityState.Modified).ToList();
            foreach (var entry in entities)
            {
                var properties = typeof(TestModel).GetProperties()// get you model properties
                        .Where(property =>
                            property != null && Attribute.IsDefined(property, typeof(IgnoreUpdateAttribute)))//which has decorated as IgnoreUpdate
                        .Select(p => p.Name);
                foreach (var property in properties)
                {
                    entry.Property(property).IsModified = false;
                }
            }

            return base.SaveChanges();
        }
//--- Code
    }

(已测试)