在旧数据库中,我必须使用通过组合键关联的嵌套表。翻译成NHibernate,我有例如一个类FcoTransportation,它有一个FcoConsignment类的子集合。但是,在一种情况下,我想仅基于组合键的一个组件加载集合,而忽略另一个组件。
映射如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
<class name="FcoLib.FcoTransportation, FcoLib" table="FCO_TRANSPORTATION">
<composite-id>
<key-property name="ID"/>
<key-property name="FK_EventID"/>
</composite-id>
<!--...snip...-->
<bag name="Consignments" table="FCO_Consignment" lazy="false" cascade="save-update">
<key>
<column name="FK_TransportationID"/>
<column name="FK_EventID"/>
</key>
<one-to-many class="FcoLib.FcoConsignment, FcoLib"/>
</bag>
<!--...snip...-->
我一直在尝试使用普通的NHibernate标准,SQL和HQL创建此查询。 这是我迄今为止在HQL中所获得的,至少可以无错误地加载传输:
String queryString = "select ft from FcoTransportation as ft";
queryString += " join ft.Consignments as fc on fc.FK_TransportationID = :ID";
var query = session.CreateQuery(queryString);
transports = query
.SetMaxResults(100)
.List<FcoTransportation>();
然而,货物的收集仍然是空的!我该如何解决这个问题??
作为一个额外的,我想通过分别在两列“ChangedDate”和“ChangedTime”中选择具有最高值的条目来淘汰任何重复的孩子。
作为最后的手段,我正在考虑完全删除复合键映射。在这种情况下,我仍然需要根据最新的ChangedDate / ChangedTime删除重复...
UPDATE :我尝试删除复合键映射,但后来我收到一个显然被抛出的错误,因为即使我尝试忽略复合外键也会强制执行。那么说服NHibernate不强制执行此操作的诀窍是什么,因为我可以在SQL Srv Mgt Studio中轻松编写SQL查询来执行此操作:
SELECT TOP 100 *
FROM [FCO_EVENT] AS e
INNER JOIN [FCO_TRANSPORTATION] AS t ON e.FK_TransportationID = t.ID
--children:
LEFT OUTER JOIN [FCO_CONSIGNMENT] AS c ON c.FK_TransportationID = t.ID
LEFT OUTER JOIN [FCO_CONSIGNMENT_LINES] AS cl ON cl.FK_ConsignmentID = c.ID
更新:建议使用联接提取,看起来很有前景,但仍然没有提取子项:
String queryString = "select ft from FcoTransportation as ft where ft.ID ='" + guid + "'";
queryString += " join fetch ft.Consignments as fc on fc.FK_TransportationID = '" + guid + "'";
更新:还建议进行所谓的“theta-style”加入,如下图所示,但在这里,未收集子集合:
String queryString = "select ft from FcoTransportation as ft, FcoConsignment as fc"
+ " where ft.ID = fc.FK_TransportationID"
+ " and ft.ID = '" + guid + "'";
注意:我只需要取出数据,而不是再将其保存。我已经有一个查询来获取每个运输的货物(最多是几十个,但通常是几个,在一些孤立的情况下几百个)。我只想通过数据库的往返量来获得经济效益。这就是为什么我希望在同时运输货物的同时取出货物。
答案 0 :(得分:1)
我认为你对此采取了错误的做法。一对多关系映射是面向对象的等价于关系数据库中的外键关系。在此上下文中,过滤或获取子集合的不同视图的能力没有意义。假设你可以这样做,NHibernate如何将更改保留到已过滤的子集合?如果NHibernate无法持久化,那么它的模型不正确。您希望通过优先选择两列中具有最高值的条目“ChangedDate”和“ChangedTime”来“清除任何重复的孩子”,这加强了这一结论。
我只想创建一个查询来返回您想要的货物。使用Future,您可以将它包装在一个方法中,该方法将返回FcoTransportation对象,并且查询将导致数据库的单次访问。
另一种选择是向FcoTransportation添加一个过滤子集合的方法。如果托运数量合理(<10000?)并且您经常需要以这种方式过滤集合,那么我会选择此选项。
答案 1 :(得分:0)
目前您只是加入而不是抓取孩子,所以尝试使用“join fetch”而不是仅仅加入:
select ft from FcoTransportation as ft join fetch ft.Consignments as fc on fc.FK_TransportationID = :ID
这应该可以解决问题。
答案 2 :(得分:0)
试试这个
select ft from FcoTransportation as ft, FcoConsignment as fc
where ft.Id = fc.Transportation.Id
我不知道从FcoConsignment到FcoTransportation的导航属性的名称,因此我将其命名为Transportation。