【问题标题】:nlog4.x ${longdate} works on Npgsql 2.2.7 but does not work on Npgsql 3.xnlog4.x ${longdate} 适用于 Npgsql 2.2.7 但不适用于 Npgsql 3.x
【发布时间】:2017-05-20 17:26:26
【问题描述】:

我正在使用 NLog4.1 版本进行日志记录。

我的“NLog.config”看起来像:

<target name="database" xsi:type="Database">
    <connectionStringName>PRODUCTION</connectionStringName>
    <commandText>
        INSERT INTO "MY"."LOG_TABLE" ( "ENTRY_DATE" ) VALUES ( @ENTRY_DATE );
    </commandText>

    <parameter name="@entry_date" layout="${longdate}"/>
</target>

当我使用 Npgsql v2.2.7 Nuget 包时,记录是可以的。

但是当将 Nuget 包升级到 Npgsql v3.2.2 并将 EntityFramework6.Npgsql 升级到 v3.1.1 时,日志记录会出现以下错误:

protected static NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
Logger.Info("Logger started.");

以下错误:

42804:“ENTRY_DATE”列的类型是没有时区的时间戳,但表达式的类型是文本

说明:在执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。

异常详细信息:Npgsql.PostgresException:42804:列“ENTRY_DATE”是没有时区的时间戳类型,但表达式是文本类型

[PostgresException (0x80004005): 42804: 列“ENTRY_DATE”是没有时区的时间戳类型,但表达式是文本类型]

网络配置更改

对于 v2.2.7:

<system.data>
    <DbProviderFactories>
        <add name="Npgsql Data Provider" invariant="Npgsql" description="Data Provider for PostgreSQL" type="Npgsql.NpgsqlFactory, Npgsql" />
    </DbProviderFactories>
</system.data>
<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
        <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
        <provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, Npgsql.EntityFramework" />
    </providers>
</entityFramework>

对于 v3.2.2:

<system.data>
    <DbProviderFactories>
        <add name="Npgsql Data Provider" invariant="Npgsql" description="Data Provider for PostgreSQL" type="Npgsql.NpgsqlFactory, Npgsql" />
    </DbProviderFactories>
</system.data>
<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
        <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
        <provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, EntityFramework6.Npgsql" />
    </providers>
</entityFramework>

Postgresql 数据库列定义:

 "ENTRY_DATE" timestamp without time zone

升级到 v3.x 后有何变化?请帮助在 v3.x 上正确使用。

提前致谢。

【问题讨论】:

  • tablo 列定义:"ENTRY_DATE" 没有时区的时间戳
  • 仅供参考,来自 NLog 数据库目标的所有数据库参数都是文本类型。也许您需要在查询中进行解析。
  • @Julian 感谢您的回复。考虑到“NLog 数据库目标是文本类型”,我可能需要编写自定义记录器类。但是我想知道在迁移到 Npgsql 新 3.x 版本而 Nlog 4.x 正确使用 Npgsql 2.2.7 时是否不需要更改代码。
  • 不需要客户记录器类。看我的回答

标签: c# postgresql entity-framework nlog


【解决方案1】:

更新答案

从 NLog 4.6 开始,可以使用 dbType 属性配置参数类型。 NLog 4.6 已于 2019 年 3 月发布。

例如

<parameter name="@entry_date" layout="${longdate}" dbType="DateTime" />

https://github.com/NLog/NLog/wiki/Database-target

dbType - DbType 的值之一(例如“Int32”、“Decimal”、“DateTime”),或带有属性名称前缀的 DBType 值,例如“SqlDbType.NChar”将在“NChar”上设置属性“SqlDbType”。另一个示例:带有 NpgsqlParameter 的“NpgsqlDbType.Json”。在 NLog 4.6 中引入。由于 NLog 4.7 不再区分大小写

原答案:

NLog中来自数据库目标的参数是文本参数。

现在看来 Npgsql/PostgreSQL/EntityFramework6 更挑剔了。

您需要将string 转换为timestamp 类型。您可以使用to_timestamp PostgreSQL 函数在查询中执行此操作:

 <commandText>
    INSERT INTO "MY"."LOG_TABLE" ( "ENTRY_DATE" ) 
    VALUES (to_timestamp(@ENTRY_DATE,  'YYYY-MM-DD H24:MI:SS.MS');
 </commandText>

C# 中的格式:yyyy-MM-dd HH:mm:ss.ffff,PostgreSQL 中的格式:YYYY-MM-DD H24:MI:SS.MS - 请参阅 PostgreSQL docs

【讨论】:

  • 谢谢@Julian。转换函数适用于 SQL 语句。
猜你喜欢
  • 1970-01-01
  • 2017-03-25
  • 1970-01-01
  • 2011-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多