C#使用PostgreSQL及其衍生产品GaussDB时(Npgsql.EntityFrameworkCore.PostgreSQL)过程中的几个问题

  PostgreSQ作为开源免费的数据库,现在正在火热的占据市场,它衍生产品,比如GaussDB在国产化替代中使用比较多,然而它们或多或少存在一个兼容问题,或者说是版本之间的问题,所以这里记录几个在使用过程中碰到的问题,做个笔记,后续有新的问题就再记录。

  问题一0A000: DISCARD statement is not yet supported.

  这个问题是连接池重置导致的一个问题,官网介绍:https://www.npgsql.org/doc/performance.html#pooled-connection-reset

  这个时候,我们可以在连接字符串中添加 No Reset On Close=true配置项,比如:  

    string connectionString = "Host=localhost;Port=5432;Database=postgres;Password=123456;User ID=postgres;No Reset On Close=true;"

 

  问题二使用EFCore执行Linq查询时,因为版本问题报错,特别是在使用GaussDB等衍生产品时,比较常见

  比如我执行一个Linq的查询时:  

    var accounts = new string[] { "zhangsan", "lisi" };
    var users = await context.Set<SysUser>().Where(f => accounts.Contains(f.Account)).ToArrayAsync();

  使用最新的 Npgsql.EntityFrameworkCore.PostgreSQL得到的SQL语句是这样的:

    SELECT s."Id", s."Account", s."Avatar", s."Birthday", s."Email", s."Name", s."NickName", s."Password", s."Phone",
    FROM sys_user AS s
    WHERE s."Account" = ANY (@__accounts_0) OR (((s."Account" IS NULL)) AND ((array_position(@__accounts_0, NULL) IS NOT NULL)))

  然后执行报错:Npgsql.PostgresException (0x80004005): 42883: function array_position(character varying[], unknown) does not exist

  很显然他是说找不到指定的函数(你的可能是其它函数),这就是版本的问题

  解决方法是在添加服务时,使用 UseRedshift方法来处理:  

    string connectionString = "Host=localhost;Port=5432;Database=postgres;Password=123456;User ID=postgres;"
        
    services.AddDbContext<MyDbContext>(options =>
    {
        options.UseNpgsql(connectionString, options =>
        {
            options.UseRedshift(true);
        });
    });

  这其实就是告诉EFCore不要使用那些不支持的属性,然后我这边上面的Linq查询就会被翻译成:  

    SELECT s."Id", s."Account", s."Avatar", s."Birthday", s."Email", s."Name", s."NickName", s."Password", s."Phone",
    FROM sys_user AS s
    WHERE s."Account" IN ('zhangsan', 'lisi')

 

  问题三日期问题(有时区和无时区时间)(  DateTimeOffsetDateTime)

  遇到报错:  

    One or more errors occurred. (Cannot write DateTime with Kind=Local 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.)

   很明显,这个是在说我们时间使用上的问题,我们数据库对应字段是 timestamp with time zone,它表示的是一个有时区的时间,但是我们类型用的是DateTime,他表示的是一个无时区的时间,所以我们要使用有时间的时间类型 DateTimeOffset,但是我们用习惯了DateTime,如果要改动,代价太大了,怎么办呢,有个兼容的办法,全局添加这两个代码就行了  

    internal class MyDbContext : DbContext
    {
        static MyDbContext()
        {
            AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
            AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
        }

        ...
    }

  

 

posted @ 2024-07-22 17:56  没有星星的夏季  阅读(234)  评论(0编辑  收藏  举报