更新到 6.0.3 后,我在 ExecuteSqlInterpolatedAsync 中遇到錯誤。好吧,我知道這是一個重大變化,但是我查看了資料庫中的所有表,并且所有列都是“沒有時區的時間戳”。并且通過模型/DbSet 進行更新或插入是可以的。
考慮到這一點,看看這段代碼:
await Database.ExecuteSqlInterpolatedAsync($@"update nfservico set
chavenfse = {chave},
lotenfse = {cLote},
lotenfse_dh = {dhRecbto},
lotenfse_sit = {sit},
lotenfse_mot = {mot}
where id = {id}");
dhRecbto 它是一個沒有指定“種類”的 DateTime 引數。運行它會給出以下錯誤:
System.InvalidCastException: Cannot write DateTime with Kind=Unspecified to PostgreSQL type 'timestamp with time zone', only UTC is supported. Note that it's not possible to mix DateTimes with different Kinds in an array/range. See the Npgsql.EnableLegacyTimestampBehavior AppContext switch to enable legacy behavior.
at Npgsql.Internal.TypeHandlers.DateTimeHandlers.TimestampTzHandler.ValidateAndGetLength(DateTime value, NpgsqlParameter parameter)
at Npgsql.Internal.TypeHandlers.DateTimeHandlers.TimestampTzHandler.ValidateObjectAndGetLength(Object value, NpgsqlLengthCache& lengthCache, NpgsqlParameter parameter)
at Npgsql.NpgsqlParameter.ValidateAndGetLength()
at Npgsql.NpgsqlParameterCollection.ValidateAndBind(ConnectorTypeMapper typeMapper)
at Npgsql.NpgsqlCommand.ExecuteReader(CommandBehavior behavior, Boolean async, CancellationToken cancellationToken)
at Npgsql.NpgsqlCommand.ExecuteReader(CommandBehavior behavior, Boolean async, CancellationToken can...
我無法理解“帶時區的時間戳”部分,就像我之前說的那樣,該欄位沒有時區。
我不得不做一個丑陋的作業:
var sql = new StringBuilder();
sql.AppendLine("update nfservico set ");
sql.AppendLine($" chavenfse = '{chave}',");
sql.AppendLine($" lotenfse = '{cLote}',");
sql.AppendLine($" lotenfse_dh = '{dhRecbto:yyyy-MM-dd HH:mm:ss}',");
sql.AppendLine($" lotenfse_sit = {sit},");
sql.AppendLine($" lotenfse_mot = '{mot}'");
sql.AppendLine($" where id = {id}");
await Database.ExecuteSqlRawAsync(sql.ToString());
有同樣問題的人嗎?不,我不想使用“EnableLegacyTimestampBehavior”開關,想要做對(至少就像在 Npgsql 6 的發行說明中找到的那樣)。
uj5u.com熱心網友回復:
這是 EF Core 的原始 SQL 支持中的一個限制。EF 型別映射——管理所發送引數的 PG 型別(timestamp 與 timestamptz)——僅由引數的 CLR 型別(DateTime)確定,而不查看其內容(即 Kind)。DateTime 的默認 EF 映射是 timestamptz,而不是時間戳;因此錯誤。請注意,這與您的實際資料庫列型別無關:這純粹是一個客戶端問題。
幸運的是,EF 的原始 SQL API 允許直接傳入 DbParameter,允許您準確指定所需的 PostgreSQL 型別:
var p = new NpgsqlParameter { Value = new DateTime(2020, 1, 1, 12, 0, 0), NpgsqlDbType = NpgsqlDbType.Timestamp };
_ = ctx.Database.ExecuteSqlInterpolatedAsync($"SELECT {p}");
這是傳遞引數的安全、正確的方法,其中 CLR 型別 (DateTime) 具有默認 PG 型別 (timestamptz),這不是您想要的(您想要時間戳)。您上面的解決方法可能在某種程度上是錯誤的,并且可能會引入不需要的時區轉換。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/444790.html
標籤:C# PostgreSQL 实体框架核心 npgsql
