You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core映射PostgreSQL jsonb_path_exists函数失败求解决方案

可行解决方案

方案1:修正DbFunction参数类型匹配

PostgreSQL的jsonb_path_exists函数第一个参数类型为jsonb,但你的实体字段定义为string,EF Core会将其作为text传入,导致函数签名不匹配。按以下步骤调整:

  1. 修改实体字段类型
    将Data字段改为NpgsqlTypes.NpgsqlJsonb或EF Core 5+支持的JsonElement:

    // 选项1:使用NpgsqlJsonb
    public NpgsqlJsonb Data { get; set; }
    
    // 选项2:使用JsonElement(EF Core 5+)
    // public JsonElement Data { get; set; }
    

    实体配置保留HasColumnType("jsonb")即可,Npgsql会自动完成映射。

  2. 修正DbFunction定义与映射

    public static class PgJsonbFunctions
    {
        [DbFunction("jsonb_path_exists", IsBuiltIn = true)]
        public static bool JsonbPathExists(NpgsqlJsonb jsonb, string path)
            => throw new NotSupportedException("仅用于EF Core LINQ查询");
    }
    

    在OnModelCreating中配置函数:

    modelBuilder.HasDbFunction(typeof(PgJsonbFunctions).GetMethod(nameof(PgJsonbFunctions.JsonbPathExists)))
                .HasName("jsonb_path_exists")
                .IsBuiltIn();
    
  3. 构建链式查询

    var query = dbContext.LayoutEntities
        .Where(l => PgJsonbFunctions.JsonbPathExists(l.Data, "$.** ? (@.\"$type\" == \"DataMatrix\")"))
        .Where(l => PgJsonbFunctions.JsonbPathExists(l.Data, "$.** ? (@.\"$type\" == \"Text\")"))
        .OrderBy(l => l.Id);
    

方案2:直接嵌入原生SQL片段

如果不想修改实体字段类型,可直接使用原生SQL构建查询:

方式A:使用FromSqlRaw

var query = dbContext.LayoutEntities
    .FromSqlRaw(@"SELECT * FROM layouts 
                  WHERE jsonb_path_exists(data, '$.** ? (@.""$type"" == ""DataMatrix"")')
                    AND jsonb_path_exists(data, '$.** ? (@.""$type"" == ""Text"")')")
    .OrderBy(l => l.Id);

方式B:结合EF.Functions.Exists

var query = dbContext.LayoutEntities
    .Where(l => EF.Functions.Exists(
        EF.Functions.FromSqlRaw(@"SELECT 1 FROM layouts 
                                  WHERE id = {0} 
                                    AND jsonb_path_exists(data, '$.** ? (@.""$type"" == ""DataMatrix"")')
                                    AND jsonb_path_exists(data, '$.** ? (@.""$type"" == ""Text"")')", l.Id)))
    .OrderBy(l => l.Id);

方案3:使用Npgsql官方JSON查询扩展(推荐)

Npgsql为EF Core提供了原生的JSON查询扩展,无需手动映射函数:

  1. 确保安装最新版Npgsql.EntityFrameworkCore.PostgreSQL包。
  2. 构建查询
    • 若字段为NpgsqlJsonb或JsonElement类型:
      var query = dbContext.LayoutEntities
          .Where(l => l.Data.JsonbPathExists("$.** ? (@.\"$type\" == \"DataMatrix\")"))
          .Where(l => l.Data.JsonbPathExists("$.** ? (@.\"$type\" == \"Text\")"))
          .OrderBy(l => l.Id);
      
    • 若字段仍为string类型,需先转换为NpgsqlJsonb:
      using NpgsqlTypes;
      
      var query = dbContext.LayoutEntities
          .Where(l => NpgsqlJsonb.Parse(l.Data).JsonbPathExists("$.** ? (@.\"$type\" == \"DataMatrix\")"))
          .Where(l => NpgsqlJsonb.Parse(l.Data).JsonbPathExists("$.** ? (@.\"$type\" == \"Text\")"))
          .OrderBy(l => l.Id);
      

内容的提问来源于stack exchange,提问作者Hille

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 07:44:51