I have the following situation:
The table I am working with has 3 columns:
table_name | column_name | data_type
------------+-------------+--------------------------
MyTable | SiteId | bigint
MyTable | Timestamp | timestamp with time zone
MyTable | Energy | real
SiteId
and Timestamp
are (together) the primary key for the table.
Timestamps are stored in UTC.
I created a record with the following information:
SiteId | Timestamp | Energy
--------+------------------------+--------
884524 | 2023-03-12 12:13:14+00 | 7
I want to find a record by SiteId
and Timestamp
and update the Energy
value.
I get errors on the update. I brought the 'problem' down to the following code:
var timestampUtc = new DateTime(2023, 3, 12, 12, 13, 14, DateTimeKind.Utc);
Expression<Func<MyTable, bool>> predicate =
s => s.SiteId == 884524 &&
s.Timestamp == timestampUtc;
var entity = context.MyTable.Where(predicate).SingleOrDefault();
entity.Energy = 15;
context.MyTable.Update(entity);
context.SaveChanges();
The SaveChanges()
call throws an exception. On the console the following info and fail information is printed:
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (8ms) [Parameters=[@p1='884524', @p2='2023-03-12T13:13:14.0000000+01:00' (DbType = DateTime), @p0='15' (Nullable = true)], CommandType='Text', CommandTimeout='30']
UPDATE "MyTable" SET "Energy" = @p0
WHERE "SiteId" = @p1 AND "Timestamp" = @p2;
fail: Microsoft.EntityFrameworkCore.Update[10000]
An exception occurred in the database while saving changes for context type 'MyHome.Models.MyHomeContext'.
Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
The info line shows that the local time is used in the update query and not the original UTC time.
When I look with the debugger, after the var entity =
statement I see that in entity
the following data is present.
entity.Timestamp {2023-03-12 13:13:14} System.DateTime
entity.Timestamp.Kind Local System.DateTimeKind
The timestamp is 'automatically' converted from UTC to local time. When the updated is posted, it looks in the database for the local time, not the 'original' UTC time.
What do I need to do to make updates work?
I think I found the source of the problem. There is/was a line in the code:
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
This changes the behavior of dealing with timestamp with time zone
fields. Also the behavior seems to be different, depending on the Postgresql server version.