在OrmLite中使用PostgreSQL聚合函数的结果映射问题
你遇到的错误是因为OrmLite的泛型Tuple映射逻辑要求返回的数据库列和Tuple泛型参数的可映射字段一一对应,而json_agg返回的是单个JSON字符串列,无法直接映射为List<BlogToBlogCategory>集合类型,导致列匹配逻辑异常抛出错误。
以下是3种可行的实现方案:
方案1:自定义DTO接收+手动反序列化JSON
首先定义接收结果的DTO类:
public class BlogWithCategories : Blog { // 接收json_agg返回的JSON字符串 public string CategoriesJson { get; set; } // 忽略OrmLite映射,直接反序列化得到子集合 [Ignore] public List<BlogToBlogCategory> Categories => System.Text.Json.JsonSerializer.Deserialize<List<BlogToBlogCategory>>(CategoriesJson); }
修改查询语句,给聚合字段加别名匹配DTO属性:
var q = db .From<Blog>(db.TableAlias("b")) .Join<BlogToBlogCategory>((b,btc) => b.Id == btc.BlogId, db.TableAlias("btc")) .GroupBy(x => x.Id) .Select("b.*, json_agg(btc) AS CategoriesJson"); var values = db.Select<BlogWithCategories>(q); // 直接访问每个元素的Categories属性即可得到子表集合
方案2:不定义DTO,用动态类型中转
如果不想新增DTO类,可以用动态类型接收查询结果后手动转换:
var q = db .From<Blog>(db.TableAlias("b")) .Join<BlogToBlogCategory>((b,btc) => b.Id == btc.BlogId, db.TableAlias("btc")) .GroupBy(x => x.Id) .Select("b.*, json_agg(btc)"); var rawResults = db.Select<dynamic>(q); var values = rawResults.Select(r => new Tuple<Blog, List<BlogToBlogCategory>>( r.ConvertTo<Blog>(), System.Text.Json.JsonSerializer.Deserialize<List<BlogToBlogCategory>>(r.json_agg.ToString()) )).ToList();
方案3:使用OrmLite原生关联查询API(无需手动写聚合SQL)
如果你的需求只是查询Blog实体和关联的BlogToBlogCategory集合,可以直接用OrmLite自带的LoadSelectAPI,不需要手动写分组和JSON聚合逻辑:
- 首先在Blog实体类中添加关联属性标记:
public class Blog { public int Id { get; set; } // 其他原有属性... // 标记为关联引用属性 [Reference] public List<BlogToBlogCategory> Categories { get; set; } }
- 直接调用LoadSelect查询:
// OrmLite会自动执行关联查询并组装父子结构 var values = db.LoadSelect<Blog>();
内容的提问来源于stack exchange,提问作者Guerrilla
相关产品推荐
相关产品推荐

