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

c# ef-core-2.2 entity-framework-core

Question

EDIT: The answer is simple, I missed the property {get; set} on my Timestamp, and so EF Core ignores the mapping. But read on if you feel so inclined.

I am using C# EF Core's InMemoryDatabase to do unit tests for my application. However, for a particular set of tests I am having a weird bug where the DateTime on some entities is being reset to the default [1/1/0001 12:00:00 AM] when I reference them later.
This is the POCO object that is being created and added to the context:

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

And here is where it is added to the 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();
}

If I breakpoint during the test right after the db.SaveChanges() line, I can see that the meters have been added to the Meters DbSet and that they have the right DateTime for the Timestamp (i.e. [1/20/2019 12:00:00 AM]). Nonetheless, when I reference the context later like so:

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

If I breakpoint at this line, every meter in db.Meters has been set to the default starting date time of [1/1/0001 12:00:00 AM]. However, the Change property still maintains the original int value as expected.

This is currently blowing my mind and I have tried several options to rectify the problem. I tried adding an intermediate step between the adding and then querying, where I would iterate over every meter and update the Timestamp, save changes, and then later query--and it still failed! I tried DateTime? Timestamp and that just sets the time to null, I've tried also adding [DatabaseGenerated(DatabaseGeneratedOption.Identity)] as that has helped when using my Npgsql database and telling it to use CURRENT_TIMESTAMP if Timestamp is ever set to null. I realize that I haven't told the InMemoryDatabase what to do with null values, but I also have never given it null values, so what gives?

Is there some setting I need to set to keep the InMemoryDatabase from touching the values after they've been set?

1
2
2/28/2019 10:01:42 PM

Accepted Answer

The issue has nothing in common with InMemory database.

The cause is a trivial mistake in your entity:

public DateTime Timestamp;

Timestamp is a field, hence is not mapped and not stored. While working with the context used to add entities, the change tracker returns the original instances, that's why you see the values you've set. But once you create a new context, the query creates new objects and of course the not mapped fields have default values.

Simply make it property

public DateTime Timestamp { get; set; }
7
2/28/2019 6:36:37 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow