gpt4 book ai didi

c# - NHibernate 中表之间的复杂关系

转载 作者:太空狗 更新时间:2023-10-30 00:45:53 26 4
gpt4 key购买 nike

我正在为遗留 Oracle 数据库编写 Fluent NHibernate 映射。挑战在于表具有复合主键。如果我完全自由,我会重新设计关系并自动生成主键,但其他应用程序必须写入同一个数据库并从中读取,所以我不能这样做。

这是我将重点关注的两个表:

alt text

示例数据

Trips table:
1, 10:00, 11:00 ...
1, 12:00, 15:00 ...
1, 16:00, 19:00 ...
2, 12:00, 13:00 ...
3, 9:00, 18:00 ...

Faults table:
1, 13:00 ...
1, 23:00 ...
2, 12:30 ...

在这种情况下,车辆 1 行驶了 3 趟,出现了 2 次故障。第一次故障发生在第二次行程中,第二次故障发生在车辆静止时。车辆2有一次行程,期间发生故障。

约束

同一辆车的行程永远不会重叠。所以这些表具有可选的一对多关系,因为每个故障要么在旅行期间发生,要么没有。如果我想在 SQL 中加入它们,我会写:

select ... 
from Faults left outer join Trips
on Faults.VehicleId = Trips.VehicleId
and Faults.FaultTime between Trips.TripStartTime and Trips.TripEndTime

然后我会得到一个数据集,其中每个错误只出现一次(正如我所说的一对多)。

请注意,没有 Vehicles 表,我也不需要。但我确实创建了一个 View ,其中包含两个表中的所有 VehicleId,因此我可以将其用作联结表。

我到底在寻找什么?

这些表很大,因为它们涵盖了多年的数据,每次我只需要获取几个小时的范围。

所以我需要一个映射和一个标准来运行类似于下面的 SQL:

select ... 
from Faults left outer join Trips
on Faults.VehicleId = Trips.VehicleId
and Faults.FaultTime between Trips.TripStartTime and Trips.TripEndTime
where Faults.FaultTime between :p0 and :p1

你有什么想法可以实现吗?

注意 1:目前应用程序不应该写入数据库,因此持久化不是必须的,尽管如果映射支持持久化,它可能在将来的某个时候有所帮助。

注2:我知道这是一个艰难的问题,所以如果你给我一个很好的答案,你将得到适当的奖励:)

感谢您阅读这个长长的问题,现在我只希望最好的:)

最佳答案

当前推荐

考虑到评论中的附加信息,我现在建议尝试使用以下类映射,而不是使用此答案后面提到的任何自定义 SQL 解决方案:

<class name="Fault" table="Faults">
<composite-id>
<key-property name="VehicleId" />
<key-property name="FaultTime" />
<key-property name="FaultType" />
<generator class="assigned" />
</id>
<many-to-one name="Trip" class="Trip">
<!-- Composite Key of Trip is calculated on the fly -->
<formula>VehicleId</formula>
<formula>
( SELECT TripStartTime
FROM Trips t
WHERE VehicleId = t.VehicleId
AND FaultTime BETWEEN t.TripStartTime AND t.TripEndTime
)
</formula>
</many-to-one>
...
</class>

<class name="Trip" table="Trips">
<composite-id>
<key-property name="VehicleId" />
<key-property name="TripStartTime" />
</composite-id>
...
</class>

使用此映射,您可以根据需要加载和查询故障实体。

过时的建议

我最初考虑的是(命名的)自定义 SQL 查询。您可以在映射文件中输入以下查询来为给定车辆加载故障对象:

<sql-query name="LoadFaultsAndTrips" xml:space="preserve">
<return class="Fault" alias="f"/>
<return-join alias="t" property="f.Trip"/>
SELECT {f.*}
, {t.*}
FROM Faults f
LEFT OUTER JOIN Trips t
ON f.VehicleId = t.VehicleId
AND f.FaultTime BETWEEN t.TripStartTime AND t.TripEndTime
WHERE f.VehicleId = ?
</sql-query>

如果您需要在没有显式查询的情况下在 Vehicle 对象上加载 Faults 集合,您可以在 XML 中尝试以下映射结构:

<class name="Vehicle">
<id name="VehicleId" type="...">
<generator class="..." />
</id>
...
<bag name="Faults" table="Faults" inverse="true">
<key column="VehicleId" />
<loader query-ref="VehicleFaultsLoader" />
</bag>
...
</class>

<sql-query name="VehicleFaultsLoader" xml:space="preserve">
<load-collection role="Vehicle.Faults" alias="f" />
<return-join alias="t" property="f.Trip"/>
SELECT {f.*}
, {t.*}
FROM Faults f
LEFT OUTER JOIN Trips t
ON f.VehicleId = t.VehicleId
AND f.FaultTime BETWEEN t.TripStartTime AND t.TripEndTime
WHERE f.VehicleId = ?
</sql-query>

此处的关键是为 Vehicle 类的 Faults 集合定义自定义集合加载器,并定义接收 Vehicle 主键作为参数的自定义 SQL 查询。我自己还没有使用过流利的 NHibernate,所以恐怕我无法帮助您解决这部分问题。

干杯,格克。

关于c# - NHibernate 中表之间的复杂关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4608317/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com