首页 > 解决方案 > ServiceStack ORMLite:带有表别名的多列 GroupBy

问题描述

我希望使用 ORMLite 按多个别名表进行分组,但我似乎遇到了问题。

当在 SqlExpression 的 GroupBy 中使用带有匿名类型的 Sql.TableAlias 时,为 group by 生成的 SQL 包含来自匿名类型的属性名称(即 AliasName."Column" As PropertyName)。

下面的代码可以重现此问题:

public class Thing
{
    public int? Id { get; set; }
}

public class Stuff
{
    public int? Id { get; set; }
    public int? ThingId { get; set; }
    public int? Type { get; set;  }
}

string brokenGroupBy = db
    .From<Thing>()
    .Join<Stuff>((thing, stuff) => stuff.ThingId == thing.Id && stuff.Type == 1, db.TableAlias("StuffTypeOne"))
    .Join<Stuff>((thing, stuff) => stuff.ThingId == thing.Id && stuff.Type == 2, db.TableAlias("StuffTypeTwo"))
    .GroupBy<Thing, Stuff>((thing, stuff) => new
    {
        ThingId = thing.Id,
        StuffTypeOneId = Sql.TableAlias(stuff.Id, "StuffTypeOne"),
        StuffTypeTwoId = Sql.TableAlias(stuff.Id, "StuffTypeTwo")
    })
    .Select<Thing, Stuff>((thing, stuff) => new
    {
        ThingId = thing.Id,
        StuffTypeOneId = Sql.TableAlias(stuff.Id, "StuffTypeOne"),
        StuffTypeTwoId = Sql.TableAlias(stuff.Id, "StuffTypeTwo")
    })
    .ToMergedParamsSelectStatement();

生成并存储在 brokenGroupBy 字符串中的 SQL 如下:

SELECT "thing"."id"      AS "ThingId", 
       StuffTypeOne."id" AS StuffTypeOneId, 
       StuffTypeTwo."id" AS StuffTypeTwoId 
FROM   "thing" 
       INNER JOIN "stuff" "StuffTypeOne" 
               ON ( ( "StuffTypeOne"."thingid" = "thing"."id" ) 
                    AND ( "StuffTypeOne"."type" = 1 ) ) 
       INNER JOIN "stuff" "StuffTypeTwo" 
               ON ( ( "StuffTypeTwo"."thingid" = "thing"."id" ) 
                    AND ( "StuffTypeTwo"."type" = 2 ) ) 
GROUP  BY "thing"."id", 
          StuffTypeOne."id" AS stufftypeoneid, 
          StuffTypeTwo."id" AS stufftypetwoid 

在这种情况下是否不支持表别名,或者在这种情况下是否有不同的方式来指定分组依据?

我已经使用 group by 中的自定义 SQL 表达式实现了我想要的结果,但我更喜欢不需要 SQL 字符串的解决方案。

标签: ormlite-servicestack

解决方案


我已经从 v5.8.1 发布了对 OrmLite 的更新,现在可在 MyGet 上使用,它还将从 Group By Expressions 中删除别名,因此您的 group by 表达式:

.GroupBy<Thing, Stuff>((thing, stuff) => new
{
    ThingId = thing.Id,
    StuffTypeOneId = Sql.TableAlias(stuff.Id, "StuffTypeOne"),
    StuffTypeTwoId = Sql.TableAlias(stuff.Id, "StuffTypeTwo")
})

现在应该生成如下内容:

thing.Id, "StuffTypeOne"."Id", "StuffTypeTwo"."Id"

虽然由于您已经在 SELECT 表达式中定义了别名,但您可以重用它们:

.GroupBy<Thing, Stuff>((thing, stuff) => new
{
    ThingId = thing.Id,
    StuffTypeOneId = "StuffTypeOneId",
    StuffTypeTwoId = "StuffTypeTwoId"
})

或者您可以将对象数组用于更简洁的表达式:

.GroupBy<Thing, Stuff>((thing, stuff) => new object[]
{
    thing.Id,
    "StuffTypeOneId",
    "StuffTypeTwoId"
})

推荐阅读