NHibernate:在映射中指定的组合键以外的其他键上加入集合
在遗留数据库中,我必须使用通过组合键关联的嵌套表。转换为 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 删除重复项...
更新:我尝试删除复合键映射,但随后我收到一个错误,显然是抛出,因为即使我尝试忽略复合外键,它们也会被强制执行。那么说服 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 + "'";
注意:我只需要取出数据,而不需要再次将其保存回来。我已经有一个查询,用于获取每种运输工具的货物(最多是几十件,但通常是几件,在某些孤立的情况下是几百件)。我只是想经济地处理数据库的往返次数。这就是为什么我希望在取出货物的同时将运输工具运出。
In a legacy database I have to work with nested tables that are associated through composite keys. Translated to NHibernate, I have e.g. a class FcoTransportation that has a collection of children of class FcoConsignment. However, in one situation, I would like to load the collection based on only one of the components of the composite key and ignore the other component.
The mapping looks like this:
<?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...-->
I have been trying to create this query this using normal NHibernate criteria, SQL and HQL.
This is what I have got so far in HQL that at least least loads the transports without errors:
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>();
However, the collection of consignments remains empty! How do I solve this !?
As an extra, I would like to weed out any duplicate children by preferring those entries with the highest values in two columns "ChangedDate" and "ChangedTime" respectively.
As a last resort, I am considering removing the composite key mapping alltogether. In that case, I would still have to remove duplicates on the basis of the latest ChangedDate/ChangedTime...
UPDATE: I have tried removing the composite key mappings, but then I receive an error that apparently is thrown, because the composite foreign keys are enforced even when I try to ignore them. So what is the trick of convincing NHibernate NOT to enforce this, since I easily can write an SQL query in SQL Srv Mgt Studio doing this:
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
UPDATE: It has been suggested to use a join fetch, which looks promising, but still no children are fetched:
String queryString = "select ft from FcoTransportation as ft where ft.ID ='" + guid + "'";
queryString += " join fetch ft.Consignments as fc on fc.FK_TransportationID = '" + guid + "'";
UPDATE: It has also been suggested to do a so-called "theta-style" join, which looks like below, but also here, the children collection is not populated:
String queryString = "select ft from FcoTransportation as ft, FcoConsignment as fc"
+ " where ft.ID = fc.FK_TransportationID"
+ " and ft.ID = '" + guid + "'";
NOTE: I only need to get data out, not save it back again. I already have a query for getting each transport's consignments (which are dozens at the very most, but usually a few and in some isolated cases a few hundred). I just want to be economic with the amount of roundtrips to the database. That is why I would like the consignments to be fetched while getting the transports out at the same time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为你对此采取了错误的方法。一对多关系映射是面向对象的,相当于关系数据库中的外键关系。在这种情况下,过滤或获取子集合的不同视图的能力没有意义。假设您可以做到这一点,NHibernate 如何将更改持久保存到已过滤的子集合中?如果 NHibernate 不能持久化它,那么它的建模是不正确的。您还希望“通过优先选择“ChangedDate”和“ChangedTime”两列中具有最高值的那些条目来清除任何重复的子项”,这强化了这一结论。
我只是创建一个查询来返回您想要的货物。使用 Future,您可以将其包装在一个方法中,该方法将在一次数据库访问中返回 FcoTransportation 对象和查询结果。
另一种选择是向 FcoTransportation 添加一个方法来过滤子集合。如果寄售数量合理(<10000?)并且您经常需要以这种方式过滤集合,那么我会选择此选项。
I think you're taking a wrong approach to this. The one-to-many relationship mapping is the object oriented equivalent of a foreign key relationship in a relational database. The ability to filter or get a different view of a child collection doesn't make sense in this context. Assuming you could do it, how could NHibernate persist changes to the filtered child collection? If NHibernate can't persist it, then it's modeled incorrectly. Your desire to also "weed out any duplicate children by preferring those entries with the highest values in two columns "ChangedDate" and "ChangedTime"" reinforces this conclusion.
I would just create a query to return the Consignments you want. Using Future, you could wrap it in a method that would return the FcoTransportation object and the query results in a single trip to the database.
Another option is to add a method to FcoTransportation that filters the child collection. If the number of Consignments is reasonable (<10000?) and you frequently need to filter the collection in this manner, then I would choose this option.
目前,您只是加入而不是获取子项,因此尝试使用“加入获取”而不仅仅是加入:
这应该可以解决问题。
Currently you are just joining not fetching the children, so try to use the "join fetch" instead of just join:
That should do the trick.
尝试一下,
我不知道从 FcoConsignment 到 FcoTransportation 的导航属性的名称,因此我将其命名为 Transportation。
Try this
I don't know the name of the navigation property from FcoConsignment to FcoTransportation so I named it Transportation.