我有一个看起来像这样的课程:
[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为这两者进行连接?
答案 0 :(得分:2)
NHibernate在单个查询中只会使用一个相同的列映射。因此,因为有两个不同的实体通过列属性映射到值“ClientId”:
在这种情况下,列映射的唯一性未被授予。它可能会造成损害,当插入或更新形式时,将应用两个实体。但我们可以使用一个技巧: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”在所有三个表中都应该是相同的......但它是另一个主题