嗨! 我有Entity Framework Core 2.xx ORM解决方案,模型中的所有对象都已创建(数据库创建时间的UTC时间戳 - 从未更新)和修改字段(更新实体时始终更新)。 我为这个非常常见的问题阅读了一些提议实现,看起来框架还不能很好地支持它,因为如果没有为每个实体单独定义映射,就没有好办法。 我找到的一个解决方法是定义一个非映射的超类,然后用它手动生成值生成步骤。因为db UTCDatetime是数据库端功能,我还必须手动定义我在db中使用utc datetime函数。我知道如何在模型生成中使用流畅的api这样做:
//这个例子缺少db调用的定义:
modelBuilder.Entity<MyObject>()
.Property(p => p.Timestamp)
.ValueGeneratedOnAddOrUpdate()
.IsConcurrencyToken();
我可以在迁移中添加utc时间生成,如下所示:
AddColumn("MyObject", "Created", n => n.DateTime(nullable: false, defaultValueSql: "GETUTCDATE()"));`
但我的问题是:如果我使用MyBaseObject超类自动完成所有操作,我该怎么办呢? (它具有这些已修改和已创建的字段,并且未自行映射)。我现在这样做,但我不知道如何定义后端创建字段调用'GetUTCDate()'
if (entityType.ClrType.IsSubclassOf(typeof(MyBaseObject)))
{
var guidProperty = entityType.FindProperty(nameof(MyBaseObject.GUID));
var createdProperty = entityType.FindProperty(nameof(MyBaseObject.Created));
var modifiedProperty = entityType.FindProperty(nameof(MyBaseObject.Modified));
entityType.AddKey(guidProperty);
entityType.SetPrimaryKey(guidProperty);
guidProperty.ValueGenerated = ValueGenerated.OnAdd;
modifiedProperty.ValueGenerated = ValueGenerated.OnAddOrUpdate;
modifiedProperty.IsReadOnlyBeforeSave = true;
//modifiedProperty.SetValueGeneratorFactory();
createdProperty.ValueGenerated = ValueGenerated.OnAdd;
createdProperty.IsReadOnlyBeforeSave = true;
entityType.AddProperty("GUID", typeof(Guid));
entityType.AddProperty("Created", typeof(DateTime));
entityType.AddProperty("Modified", typeof(DateTime));
entityType.AddIndex(modifiedProperty);
entityType.AddIndex(createdProperty);
}
答案 0 :(得分:3)
我建议创建一个约束泛型方法或类,并在里面使用普通的流畅API来配置公共属性。
例如,在构造函数中接收ModelBuilder
的泛型类:
class MyBaseObjectConfiguration<TEntity> where TEntity : MyBaseObject
{
public MyBaseObjectConfiguration(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TEntity>()
.HasKey(e => e.GUID);
modelBuilder.Entity<TEntity>()
.Property(e => e.GUID)
.ValueGeneratedNever();
modelBuilder.Entity<TEntity>()
.Property(e => e.Created)
.ValueGeneratedOnAdd()
.HasDefaultValueSql("GETUTCDATE()");
modelBuilder.Entity<TEntity>()
.Property(e => e.Modified)
.ValueGeneratedOnAddOrUpdate()
.HasDefaultValueSql("GETUTCDATE()")
.IsConcurrencyToken();
}
}
并使用OnModelCreating
内的反射调用它:
foreach (var type in modelBuilder.Model.GetEntityTypes().Where(t => t.ClrType.IsSubclassOf(typeof(MyBaseObject))))
Activator.CreateInstance(typeof(MyBaseObjectConfiguration<>).MakeGenericType(type.ClrType), modelBuilder);