EF Core映射PostgreSQL jsonb_path_exists函数失败求解决方案
可行解决方案
方案1:修正DbFunction参数类型匹配
PostgreSQL的jsonb_path_exists函数第一个参数类型为jsonb,但你的实体字段定义为string,EF Core会将其作为text传入,导致函数签名不匹配。按以下步骤调整:
修改实体字段类型
将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会自动完成映射。修正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();构建链式查询
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查询扩展,无需手动映射函数:
- 确保安装最新版
Npgsql.EntityFrameworkCore.PostgreSQL包。 - 构建查询
- 若字段为
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
相关产品推荐
相关产品推荐

