9

我想使用类似于此处描述的方法来实现时间属性,使用实体框架代码优先进行数据库存储。

我希望它优化以获取当前值并延迟加载历史记录,但我不想为每次使用都在父实体中添加样板代码,就像上面链接中的方法一样。

目前我有类似下面的代码,按照惯例,它会产生如下代码所示的数据库模式。

这将按我的需要运行,但出于性能原因,我想避免获取当前属性值所需的连接(即,我想将 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)
4

0 回答 0