我想使用类似于here描述的方法实现时态属性,使用Entity Framework代码优先进行数据库存储。
我希望它针对获取当前值进行了优化,并且对历史记录进行了延迟加载,但是我不希望必须在父实体中为每次使用添加样板代码,就像上面链接中的方法一样
目前,我有类似下面的代码,按照惯例,会产生数据库模式,如下面的代码所示。
这将按我的需要运行,但出于性能原因,我想避免获取当前属性值所需的连接(即我想将TemporalStrings.CurrentValue DB列移动到Entities.Name)
如果我尝试
modelBuilder.Entity<Entity>().Property(o => o.Name.CurrentValue).HasColumnName("Name");
它没有用。我得到了像
这样的例外The type 'ConsoleApplication1.TemporalString' has already been configured as an entity type. It cannot be reconfigured as a complex type.
我是否可以通过某种方式实现此映射,或者是否有更好的方法来实现此功能?
代码:
public class TemporalString
{
public int Id { get; set; }
public string CurrentValue { get; set; } // Setter would be customized to append to History.
public virtual List<TemporalStringValue> History { get; set; }
// Other methods such as string ValueAt(DateTime) would exist.
}
public class TemporalStringValue
{
public int Id { get; set; }
public DateTime EffectiveFrom { get; set; }
public string Value { get; set; }
}
public class Entity
{
public int Id { get; set; }
public virtual TemporalString Name { get; set; }
}
public class TestDbContext : DbContext
{
public DbSet<Entity> Entities { get; set; }
public DbSet<TemporalString> TemporalStrings { get; set; }
public DbSet<TemporalStringValue> TemporalStringValues { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//modelBuilder.Entity<Entity>().Property(o => o.Name.CurrentValue).HasColumnName("Name");
// TODO: Map DB column TemporalStrings.CurrentValue to DB column Entities.Name?
}
}
internal class Program
{
private static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<TestDbContext>());
using (var context = new TestDbContext())
{
var entity = new Entity
{
Name = new TemporalString
{
CurrentValue = "Current Value",
History = new List<TemporalStringValue>
{
new TemporalStringValue
{
EffectiveFrom = DateTime.UtcNow,
Value = "Current Value"
},
new TemporalStringValue
{
EffectiveFrom = DateTime.UtcNow.AddMonths(-1),
Value = "Old Value"
},
new TemporalStringValue
{
EffectiveFrom = DateTime.UtcNow.AddMonths(-2),
Value = "Older Value"
}
}
}
};
context.Entities.Add(entity);
context.SaveChanges();
}
Console.Write("Done.");
Console.ReadKey();
}
}
结果架构:
Entities
(PK) Id
(FK) Name_Id (references TemporalStrings.Id)
TemporalStrings
(PK) Id
CurrentValue
TemporalStringValues
(PK) Id
EffectiveFrom
Value
(FK) TemporalString_Id
所需的架构:
Entities
(PK) Id
(FK) Name_Id (references TemporalStrings.Id)
Name (formerly TemporalStrings.CurrentValue)
TemporalStrings
(PK) Id
TemporalStringValues
(no change)