【发布时间】:2020-12-24 19:25:39
【问题描述】:
从使用 PHP 开始,使用 Timestamps 相当直接,但使用 Entity Framework,这有点令人头疼。
【问题讨论】:
标签: c# sql-server entity-framework entity-framework-core timestamp
从使用 PHP 开始,使用 Timestamps 相当直接,但使用 Entity Framework,这有点令人头疼。
【问题讨论】:
标签: c# sql-server entity-framework entity-framework-core timestamp
这是一个对我有用的解决方案。 首先,我有一个所有实体都继承自的 Baseentity:
public abstract class DbEntity
{
[Column("created_at")]
public DateTime CreatedAt { get; set; } = DateTime.Now;
[Column("updated_at")]
public DateTime UpdatedAt { get; set; } = DateTime.Now;
}
然后我为UpdateMethod添加了一个扩展方法:
public static class DbSetExtension
{
public static EntityEntry<TEntity> UpdateCustom<TEntity>(this DbSet<TEntity> dbSet, TEntity dbEntity)
where TEntity : class
{
dbEntity.GetType().GetProperty("UpdatedAt")?.SetValue (dbEntity, DateTime.Now, null);
return dbSet.Update(dbEntity);
}
}
这对我来说很好。我会感谢其他人如何处理这种情况的反馈。
P.S:即使在为列设置默认 SQL 之后,[DatabaseGenerated(DatabaseGeneratedOption.Computed)] 方法对我也不起作用。
【讨论】:
我很确定您正在使用时间戳来处理一些并发冲突。 在 Entity Framework (Core) 中实际上有两种方法
您可以使用实体类上的数据注释来配置并发令牌。
public class BookEntity
{
public int BookId {get; set;}
public string Title {get; set;}
// This tells EF that this property is a concurrency token,
// which means EF will check it hasn't changed when you update it
[ConcurrencyCheck]
public DateTime PublishedOn {get; set;}
// Other properties follow...
}
也可以使用fluent API配置并发检查
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<BookEntity>()
.Property(p=> p.PublishedOn)
.IsConcurrencyToken();
// ...other configurations follow...
}
您可以使用实体类上的数据注释来配置时间戳。
public class BookEntity
{
public int BookId {get; set;}
public string Title {get; set;}
// This tells EF to mark ChangeCheck property as a timestamp,
// This causes EF to check this when updating to see if this has changed
[Timestamp]
public byte[] ChangeCheck {get; set;}
// Other properties follow...
}
使用 Fluent API 配置时间戳
protected override void OnModelCreating(ModelBuilder builder)
{
// Value of ChangeCheck will be changed each time the row
// created/updated
builder.Entity<BookEntity>()
.Property(p=> p.ChangeCheck)
.IsRowVersion;
// ...other configurations follow...
}
这两种配置都会在表中创建一个列,只要对该表进行 INSERT 或 UPDATE,数据库服务器就会自动更改该列。
这只能通过 Fluent API 完成
public class BookEntity
{
public int BookId {get; set;}
public string Title {get; set;}
// Column you set up as computed
// You give it a private setter, as its a read-only property
public DateTime DateModified {get; private set;}
// Other properties follow...
}
然后您通过 Fluent API 配置列。
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<BookEntity>()
.Property(p=> p.DateModified)
.HasComputedColumnSql("getutcdate()")
.ValueGeneratedOnAddOrUpdate();
// ...other configurations follow...
}
.HasComputedColumnSql("getutcdate()") 将告诉 EF 计算列的值;在这种情况下,要获取当前的 UTC 日期时间,然后 .ValueGeneratedOnAddOrUpdate(),将让 EF 知道该列已计算,因此应在进行任何更新时更新该列。
【讨论】:
[Timestamp] 可以实现并发,最终用户不会看到它实际更新的时间