在 OrmLite 中使用 PostgreSQL 聚合函数

Using PostgreSQL aggregate functions with OrmLite

我正在尝试弄清楚如何使用 OrmLite 处理使用聚合函数的查询的查询结果。

例如接受这个查询:

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 values = db.Select<Tuple<Blog, List<BlogToBlogCategory>>>(q);

它生成正确的 SQL:

SELECT b.*, json_agg(btc) 
FROM "blog" "b" INNER JOIN "blog_to_blog_category" "btc" ON ("b"."id" = "btc"."blog_id")
GROUP BY "b"."id"

但是解析结果报错:

Column must be between 0 and 19

我不确定如何将查询结果解析为父 table 和子 table 列表。

可能吗?

返回 JSON 函数与 return 返回一个额外的字符串列相同。由于您不能将元组与 Table 类型和标量值混合使用,因此您需要另一种方法来访问其他字符串值。

您可以将自定义结果解析为 dynamic result set,单独访问所有列,但在这种情况下,您可以创建自定义结果 class,其中包含额外的字符串列和 return 键入的结果,例如:

public class BlogResult : Blog
{
    public string Json { get; set; }

    private List<BlogToBlogCategory> results;
    public List<BlogToBlogCategory> Results => 
        results ??= Json.FromJson<List<BlogToBlogCategory>>();
}

您可以在哪里 select 进入自定义类型模型:

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 Json");
    
var values = db.Select<BlogResult>(q);

但是如果您的 PostgreSQL 列名称使用 snake_case 并且您的 C# 类型使用 PascalCase 您将需要使用自定义序列化这允许在不同 属性 样式的外壳之间进行更宽松的映射,例如:

public static class CustomJsonSerializer
{
    public static T FromJson<T>(string json)
    {
        using var scope = JsConfig.With(new Config { 
            PropertyConvention = PropertyConvention.Lenient });
        return json.FromJson<T>();
    }
}

public class BlogResult : Blog
{
    public string Json { get; set; }

    private List<BlogToBlogCategory> results;
    public List<BlogToBlogCategory> Results => results ??= 
        CustomJsonSerializer.FromJson<List<BlogToBlogCategory>>(Json);
}