31

我正在尝试向CreatedDate模型中的实体添加属性,并且正在使用 EF5 Code First。我希望这个日期一旦设置就不会更改,我希望它是 UTC 日期。我不想使用构造函数,因为我的模型中有许多实体,我想从包含该CreatedDate属性的抽象类继承,并且我不能强制使用接口的构造函数。

我尝试了不同的数据注释,并尝试编写一个数据库初始化程序,该初始化程序将获取特定的实体类型并编写一个更改约束,其getdate()默认值为正确的table_nameand column_name,但我无法正确编写该代码。

请不要让我参考AuditDbContext - Entity Framework Auditing ContextEntityFramework.Extended工具,因为它们在这里没有我需要的功能。

更新

MyCreatedDate为空,SaveChanges()因为我将 ViewModel 传递给我的视图,该视图正确地没有CreatedDate在其中调用审计属性。即使我将模型传递给我的视图,我也不会CreatedDate在视图中编辑或存储它。

我在这里读到我可以添加[DatabaseGenerated(DatabaseGeneratedOption.Identity)],这将告诉 EFCreatedDate在插入和更新之后正确存储,但不允许我的应用程序更改它:但我只是Cannot insert explicit value for identity column in table when IDENTITY_INSERT is set to OFF通过添加此属性得到一个错误。

我即将切换到 EF Model First,因为这个简单的数据库要求在 Code First 中实现是荒谬的。

4

7 回答 7

70

这是我的做法:

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreatedDate{ get; set; }

在我迁移的 Up() 方法中:

AddColumn("Agents", "CreatedDate", n => n.DateTime(nullable: false, defaultValueSql: "GETUTCDATE()"));
于 2013-01-18T12:24:49.840 回答
28

在您的上下文中覆盖 SaveChanges-Method:

public override int SaveChanges()
{
  DateTime saveTime = DateTime.UtcNow;
  foreach (var entry in this.ChangeTracker.Entries().Where(e => e.State == (EntityState) System.Data.EntityState.Added))
   {
     if (entry.Property("CreatedDate").CurrentValue == null)
       entry.Property("CreatedDate").CurrentValue = saveTime;
    }
    return base.SaveChanges();

}

由于评论而更新:只有新添加的实体才会设置日期。

于 2013-01-17T18:30:19.443 回答
4

好的,所以这里的主要问题是 CreatedDate 每次我调用 SaveChanges 时都会被更新,并且由于我没有将 CreatedDate 传递给我的视图,它被实体框架更新为 NULL 或 MinDate。

解决方案很简单,知道我只需要在 EntityState.Added 时设置 CreatedDate,我只需在 SaveChanges 覆盖中执行任何工作之前设置我的 entity.CreatedDate.IsModified = false,这样我就忽略了来自更新的更改,如果它是添加 CreatedDate 将在几行之后设置。

于 2013-01-18T04:47:59.937 回答
4

类似于Stephans 的答案,但具有反射,并且还忽略所有用户(外部)更新的创建/更新时间。显示要点

  public override int SaveChanges()
        {
            foreach (var entry in ChangeTracker.Entries().Where(x => x.Entity.GetType().GetProperty("CreatedTime") != null))
            {
                if (entry.State == EntityState.Added)
                {
                    entry.Property("CreatedTime").CurrentValue = DateTime.Now;
                }
                else if (entry.State == EntityState.Modified)
                {
                    // Ignore the CreatedTime updates on Modified entities. 
                    entry.Property("CreatedTime").IsModified = false;
                }

                // Always set UpdatedTime. Assuming all entities having CreatedTime property
                // Also have UpdatedTime
                // entry.Property("UpdatedTime").CurrentValue = DateTime.Now;
                // I moved this part to another foreach loop
            }

            foreach (var entry in ChangeTracker.Entries().Where(
                e => 
                    e.Entity.GetType().GetProperty("UpdatedTime") != null && 
                    e.State == EntityState.Modified || 
                    e.State == EntityState.Added))
            {
                entry.Property("UpdatedTime").CurrentValue = DateTime.Now;
            }

            return base.SaveChanges();
        }
于 2015-06-28T09:39:17.410 回答
2

Code First 目前不提供提供列默认值的机制。

您将需要手动修改或创建基类以自动更新 CreatedDate

public abstract class MyBaseClass
{
    public MyBaseClass()
    {
        CreatedDate = DateTime.Now;
    }
    public Datetime CreatedDate { get; set; }
}
于 2013-01-18T10:47:15.517 回答
2

对于 EF Core,您可以在此处找到 MS 推荐的解决方案: 默认值

在 DBContext 中使用 Fluent API:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Created)
        .HasDefaultValueSql("getdate()");
}
于 2018-10-23T07:55:33.260 回答
-1
Accounts account;
account.Acct_JoinDate = DateTime.Now.ToUniversalTime();
data.Accounts.Add(account);
data.SaveChanges();

为什么不在模型创建时给出时间戳?类似于这里的这些帐户。

于 2013-01-17T18:19:14.910 回答