提问者:小点点

C#-“DateTime.UtcNow”以被视为超出Postgres DB范围的格式输出日期


我换了一台新的笔记本电脑(Windows10i5),并试图设置我的笔记本电脑。NET应用程序。我遇到了一个奇怪的问题,花了我很多时间。在我的应用程序中,我将当前日期时间以UTC格式存储在Postgres DB表中。c#命令DateTime。UtcNow将日期格式输出为

14-12-2021 13:50:57

当上述日期通过要存储在Postgres Db中的insert查询传递时,它抛出错误如下

错误:日期/时间字段值超出范围:"14-12-2021 13:50:57"

更奇怪的是,在我的旧笔记本电脑上(同样的操作系统-视窗10 i3),同样的代码工作正常,并给出日期的输出

12/14/2021 07:24:24上午

这种格式被Postgres DB接受。

表的设计如下所示

CREATE TABLE IF NOT EXISTS public."Log"
(
    "Id" bigint NOT NULL DEFAULT nextval('"Log_Id_seq"'::regclass),
    "QueueId" uuid NOT NULL,
    "MessageId" character varying(100) COLLATE pg_catalog."default",
    "LogTime" timestamp without time zone,   
   
    CONSTRAINT "Log_pkey" PRIMARY KEY ("Id")
)

日期时间生成的值。UtcNow正在传递到LogTime列中。

下面是构成Postgres查询的c#代码。

string query = $@"INSERT INTO public.""Log""(
                            ""QueueId"", 
                            ""LogTime"", 
                            ""Message"", 
                            )
                            VALUES(
                            '{req.QueueId}', 
                            '{req.LogTime}', 
                            '{(item.Message.Length > 100 ? item.Message.Substring(0, 100) : item.Message)}'                           
                            RETURNING ""Id"";";

相同的代码在具有相同操作系统的不同机器上的行为不同。任何线索都将不胜感激。谢谢你的帮助。


共2个答案

匿名用户

我重复上面的评论,因为您在编写{req.LogTime}时正在转换字符串中的日期时间,因此代码为数据库创建了一个解析问题,因为它需要将该字符串转换回timespan以将其插入列中。这不仅在转换字符串时容易产生不同的结果(一台电脑认为日期的正确格式是“MM-dd”,另一台电脑认为是“dd-MM”),而且还造成了一个众所周知的漏洞,称为Sql注入
只需使用参数将值传递给数据库即可
使用适当的类型定义参数,值的解析不再有歧义,数据库也不会受到脚本孩子尝试世界上最简单的黑客攻击的影响。

string query = $@"INSERT INTO public.""Log""(
                  ""QueueId"", LogTime"", ""Message"")
                  VALUES(@qid, @ltime, @msg)                           
                  RETURNING ""Id"";";

using (var cmd = new NpgsqlCommand(query, conn))
{
    cmd.Parameters.Add("@qid", NpgsqlDbType.Uuid).Value = req.QueueId;
    cmd.Parameters.Add("@ltime", NpgsqlDbType.Timestamp).Value = req.LogTime;
    cmd.Parameters.Add("@msg", NpgsqlDbType.Varchar).Value = 
         (item.Message.Length > 100 ? item.Message.Substring(0, 100) : item.Message);
   var id = cmd.ExecuteScalar();
}

匿名用户

设置日期样式以匹配您的输入。这个对我很有用:

SET DateStyle to DMY;
SELECT '14-12-2021 13:50:57'::TIMESTAMP