所以我花了几个小时寻找答案,但似乎找不到任何有意义的答案。
public class Game
{
public virtual Guid ID { get; set; }
public virtual ResultStructure Structure { get; set; }
public virtual List<Result> Results { get; set; }
}
public class Result
{
public virtual Player Player { get; set; }
public virtual int Position { get; set; }
}
public class ResultStructure
{
public virtual Guid ID { get; set; }
public virtual List<ResultOutcomes> Outcomes { get; set;}
}
public class ResultOutcomes
{
public virtual int Position { get; set; }
public virtual int Points { get; set; }
}
public class PlayerSummary
{
public virtual Player Player { get; set; }
public virtual int Points { get; set; }
}
我想做的是获得一份玩家列表,以及他们在许多不同游戏中获得的积分(game
上方有多个实体包含游戏列表)。因此,查询的最终结果将是List<PlayerSummary>
。我正在查找的SQL看起来像这样:
SELECT p.*, Sum(rs.points) FROM result r
JOIN player p on r.playerid = p.id
JOIN game g on r.gameid = g.id
JOIN resultstructure rs on g.resultstructureid = rs.id
JOIN resultoutcomes ro on rs.id = ro.resultstructureid AND ro.position = r.position
注意,我还需要对结构实体进行一些查询/求和,这就是它被包括在内的原因。
我正在尝试使用NHibernate,使用TypeSafe的东西来实现这一点,我的计划是让应用程序与数据库无关,所以我不能使用直接SQL(目前它使用的是Postgres,但我可能会在某个时候转到SQL服务器)。
我并不特别想在使用那些神奇字符串的地方使用"HQL"之类的东西,所以我尝试使用Linq或QueryOver/Query。
有人能给我指正确的方向吗?
在我的情况下,上述情况似乎是可能的,因为存在关系,只是不直接。
您可以使用JoinAlias
。
基本区别在于,使用JoinAlias
,您可以将多个表连接到同一个基表,其中与使用JoinQueryOver
一样,它通过仅将每个表连接到前一个表的表进行线性级数。
所以查询看起来是这样的。
Result resultAlias = null;
ResultOutcome outcomeAlias = null;
ResultStructure structureAlias = null;
var results = Session.QueryOver(() => resultAlias) // Assigns resultAlias so it can be used further in the query.
.Inner.JoinQueryOver(x => x.Game) // returns a QueryOver Game so you can do a where on the game object, or join further up the chain.
.Inner.JoinAlias(x => x.ResultStructure, () => structureAlias) // joins on the Structure table but returns the QueryOver for the Game, not the structure.
.Inner.JoinAlias(() => structureAlias.Outcomes, () => outcomeAlias) // same again for the outcomes
.Where(() => resultAlias.Position == outcomeAlias.Position)
.Select(
Projections.Group(() => resultAlias.Player),
Projections.Sum(() => outcomeAlias.Points)
);
这应该给人们一个想法。这样做的不利之处在于,对"Position"的限制并没有发生在Join中,而是发生在Where子句中。我很高兴听到任何可以选择这样做的人的声音,因为这会迫使数据库查询计划器走特定的路线。
仍在进行转换和排序,但这让我走得更远。