通过复杂的非相关实体加入nhibernate查询

问题描述:

所以我花了最近几个小时寻找答案,我似乎无法找到任何有意义的东西。通过复杂的非相关实体加入nhibernate查询

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。

任何人都可以指向正确的方向吗?

+0

这是您应该使用HQL的**确切**情况。 “魔术串”并不意味着你的想法。 – 2013-02-14 15:18:23

+0

我真的想要类型安全的东西,我的确了解HQL ish,并且我意识到它可能会做我所需要的,但我想保留所有内容,并且我在大多数部分都使用Query。 – Martin 2013-02-14 15:26:41

+0

@DiegoMijelshon我已经添加了我的解决方案,可以详细说明为什么我应该使用HQL而不是我提出的解决方案? – Martin 2013-02-14 18:50:37

看来,以上是可能的在我的情况,因为有一种关系,它只是不直接。可以使用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) 
    ); 

这应该给人的想法。不利之处在于对“位置”的限制不会发生在Join上,而是发生在Where子句中。我很高兴听到任何有这样做的人的选择,因为这会迫使数据库查询计划者停止一个特定的路线。

仍在研究转换和排序,但这让我有更多的了解。

+1

因为它是所有内部联接,所以应该不会考虑额外联接标准的位置......对吗? – dotjoe 2013-02-14 20:11:04

+0

以及它们并不都是“结果”的连接,从编码的角度来看它确实很重要。 JoinAlias可能并不重要,因为它会尝试与Result而不是Game进行连接,所以无法将JoinString结果放在JoinQueryOver之前。 – Martin 2013-02-14 20:46:26