为什么 C# EF Core 会删除使用块之间的值?

Why does C# EF Core remove values between using blocks?

编辑:答案很简单,我错过了 属性 {get;在我的时间戳上设置},因此 EF Core 会忽略映射。但如果您愿意,请继续阅读。

我正在使用 C# EF Core 的 InMemoryDatabase 为我的应用程序进行单元测试。但是,对于一组特定的测试,我遇到了一个奇怪的错误,当我稍后引用它们时,某些实体上的 DateTime 被重置为默认值 [1/1/0001 12:00:00 AM]
这是正在创建并添加到上下文中的 POCO 对象:

    public class Meter
    {
        [Key]
        public long Id { get; set; }
        public DateTime Timestamp;
        public int Change { get; set; }
    }

这里是它被添加到 DbContext 的地方:

options = new DbContextOptionsBuilder().UseInMemoryDatabase("TestDB");
using (var db = new CustomContext(options))
{
    for (int i = 0; i < 10; i++)
    {
        var meter = new Meter {Timestamp = new DateTime(2019, 1, 20), Change = i};
        db.Meters.Add(meter);
    }
    db.SaveChanges();
}

如果我在 db.SaveChanges() 行之后的测试期间断点,我可以看到仪表已添加到 Meters DbSet 并且它们具有正确的时间戳日期时间(即 [1/20/2019 12:00:00 AM]). 尽管如此,当我稍后像这样引用上下文时:

using (var db = new CustomContext(options))  //Same options as I used before
{
    var times = db.Meters.Select(m => m.Timestamp);
}

如果我在此行断点,db.Meters 中的每个仪表都已设置为 [1/1/0001 12:00:00 AM] 的默认开始日期时间。但是,Change 属性 仍按预期保持原始 int 值。

这让我很震惊,我已经尝试了几种方法来解决这个问题。我尝试在添加和查询之间添加一个中间步骤,我将遍历每个仪表并更新时间戳,保存更改,然后再查询——但它仍然失败了!我尝试了 DateTime? Timestamp 并且只是将时间设置为空,我还尝试添加 [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 因为这在使用我的 Npgsql 数据库时有所帮助并告诉它使用 CURRENT_TIMESTAMP 如果时间戳是曾经设置为空。我意识到我没有告诉 InMemoryDatabase 如何处理空值,但我也从来没有给它空值,所以给出了什么?

是否需要设置一些设置以防止 InMemoryDatabase 在设置值后触及这些值?

此问题与 InMemory 数据库没有任何共同之处。

原因是您实体中的一个小错误:

public DateTime Timestamp;

Timestamp 是一个 字段 ,因此未映射且未存储。在使用用于添加实体的上下文时,更改跟踪器 returns 原始实例,这就是为什么您会看到已设置的值。但是一旦你创建了一个新的上下文,查询就会创建新的对象,当然没有映射的字段有默认值。

干脆属性

public DateTime Timestamp { get; set; }