同一列上的多个多对一连接错误地导致执行SELECT

时间:2012-11-08 18:52:36

标签: c# nhibernate

我有一个看起来像这样的课程:

[Class(Table = "SessionReportSummaries", Mutable = false)]
public class SessionReportSummaries
{        
    [ManyToOne(Column = "ClientId", Fetch = FetchMode.Join)]
    public Client Client { get; private set; }

    [ManyToOne(Column = "ClientId", Fetch = FetchMode.Join)]
    public ClientReportSummary ClientReportSummary { get; private set; }
}

SessionReportSummaries视图有一个ClientId列,我正在尝试使用此列连接Client对象和ClientReportSummary对象。

不幸的是,NHibernate只想加入类中定义的第一个,并且总是为第二个执行SELECT。因此,在这种情况下,NHibernate首先使用以下命令查询数据库:

SELECT {stuff} FROM SessionReportSummaries ... left outer join Clients on this.ClientId=Clients.Id ...

(有很多其他联接),然后是其中的N:

SELECT {stuff} FROM ClientReportSummary WHERE ClientReportSummary.ClientId = '{id goes here}'

每个N个客户一个。这会导致糟糕的表现。

如果我交换Client和ClientReportSummary对象的位置,那么NHibernate会将ClientReportSummary加入SessionReportSummaries对象,并为每个Client对象执行select。

有谁知道如何让NHibernate为这两者进行连接?

1 个答案:

答案 0 :(得分:2)

NHibernate在单个查询中只会使用一个相同的列映射。因此,因为有两个不同的实体通过列属性映射到值“ClientId”:

  • [ManyToOne(Column =“ClientId”,Fetch = FetchMode.Join)]
  • [ManyToOne(Column =“ClientId”,Fetch = FetchMode.Join)]

在这种情况下,列映射的唯一性未被授予。它可能会造成损害,当插入或更新形式时,将应用两个实体。但我们可以使用一个技巧:FORMULA映射

[Class(Table = "SessionReportSummaries", Mutable = false)]
public class SessionReportSummaries
{        
    [ManyToOne(Column = "ClientId", Fetch = FetchMode.Join)]
    public Client Client { get; private set; }

    [ManyToOne(Formula = "ClientId", Fetch = FetchMode.Join)]
    public ClientReportSummary ClientReportSummary { get; private set; }
}

现在NHibernate将一个colum映射作为真实关系,并将第二个(在formula中定义)评估为另一个。现在将使用单个select语句

每当formula用于映射(而不是column)时,都应将其标记为insert="false"update="false"。我们只需要一个SELECT。 (否则我们可以将具有不同ClientId的客户端和ClientReportSummary附加到SessionReportSummaries实体 - 这将违反异常......

第二种方法可能是一对一的映射,其中“ClientId”在所有三个表中都应该是相同的......但它是另一个主题