nlog4.x ${longdate} 适用于 Npgsql 2.2.7 但不适用于 Npgsql 3.x

nlog4.x ${longdate} works on Npgsql 2.2.7 but does not work on Npgsql 3.x

我正在使用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: column "ENTRY_DATE" is of type timestamp without time zone but expression is of type text

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: Npgsql.PostgresException: 42804: column "ENTRY_DATE" is of type timestamp without time zone but expression is of type text

[PostgresException (0x80004005): 42804: column "ENTRY_DATE" is of type timestamp without time zone but expression is of type text]

网络配置更改

对于 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.

上正确使用

提前致谢。

更新答案

从 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 - One of the values of DbType (e.g. "Int32", "Decimal", "DateTime"), or a value of DBType like prefixed with the property name, e.g. "SqlDbType.NChar" will set the property "SqlDbType" on "NChar". Another example: "NpgsqlDbType.Json" with NpgsqlParameter. Introduced in NLog 4.6. Since NLog 4.7 not case-sensitive any more

原回答:

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