PostgreSQL中用EF操作jsonb字段报错:输入字符串格式不正确
问题根源
你写的SQL里,JSON字符串被双重转义了:\"是HTML转义的引号(原本的"被转成"),又在字符串里加了反斜杠转义,导致数据库收到的是不合法的JSON格式(比如\"age\"不是有效的JSON键名),自然触发格式错误。另外直接硬编码换行符\r\n也没必要,PostgreSQL的jsonb不关心换行,只要结构合法就行。
解决方法
方法1:修正SQL字符串的转义
把HTML转义的\"还原成普通双引号,同时确保SQL里的字符串用单引号正确包裹,不需要额外转义双引号(因为JSON内部的双引号不属于SQL字符串的边界)。修正后的SQL应该是:
INSERT INTO example_table (id, name, details) VALUES (1, 'john','{"age": "17"}') ON CONFLICT (name) DO NOTHING
对应的C#代码:
_context.ExecuteSqlRaw("INSERT INTO example_table (id, name, details) VALUES (1, 'john','{\"age\": \"17\"}') ON CONFLICT (name) DO NOTHING");
这里C#字符串里的双引号用\"转义,确保传到数据库的是{"age": "17"}这个合法的JSON。
方法2:用参数化查询(推荐)
直接拼接SQL字符串容易出转义问题,还可能有SQL注入风险,用参数化查询更安全可靠:
var id = 1; var name = "john"; var details = "{\"age\": \"17\"}"; // 或者用序列化工具把对象转成JSON字符串 _context.ExecuteSqlRaw( "INSERT INTO example_table (id, name, details) VALUES ({0}, {1}, {2}) ON CONFLICT (name) DO NOTHING", id, name, details );
如果你的details是C#对象,可以用System.Text.Json或Newtonsoft.Json序列化成JSON字符串再传入,比如:
var detailsObj = new { age = "17" }; var detailsJson = JsonSerializer.Serialize(detailsObj); _context.ExecuteSqlRaw( "INSERT INTO example_table (id, name, details) VALUES ({0}, {1}, {2}) ON CONFLICT (name) DO NOTHING", 1, "john", detailsJson );
方法3:用EF Core的原生Upsert(更符合EF用法)
如果你不想写原生SQL,可以用EF Core 7+支持的OnConflict逻辑,直接操作实体类:
var entity = new ExampleTable { Id = 1, Name = "john", Details = JsonSerializer.SerializeToElement(new { age = "17" }) }; _context.ExampleTable.Add(entity); _context.SaveChanges(); // 或者用Upsert扩展(需安装Microsoft.EntityFrameworkCore.Relational包) _context.ExampleTable .Upsert(entity) .On(e => e.Name) .DoNothing() .Execute();
这里假设你的实体类里Details字段对应数据库的jsonb类型,EF Core会自动处理JSON的序列化和转义。
内容的提问来源于stack exchange,提问作者user2382627
相关产品推荐
相关产品推荐

