2

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

我正在使用 C# EF Core 的 InMemoryDatabase 为我的应用程序进行单元测试。但是,对于一组特定的测试,我遇到了一个奇怪的错误,[1/1/0001 12:00:00 AM]当我稍后引用它们时,某些实体上的 DateTime 被重置为默认值。
这是正在创建并添加到上下文中的 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 并且它们具有正确的 DateTime 时间戳(即[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 在设置值后触摸它们?

4

1 回答 1

7

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

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

public DateTime Timestamp;

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

只需使其成为财产

public DateTime Timestamp { get; set; }
于 2019-02-28T18:36:37.753 回答