ポジションが関連するポジションを持つことができるポジションのテーブルがあり (必ずしもそうとは限りません)、すべてのポジションには最終更新日があります。次に、2 つの特定の日付の間に変更された (特定のタイプの) すべてのポジションを取得したいと考えています (つまり、「メイン」ポジションまたは関連するポジションが変更されました)。SQL では、これを次のように行います。
SELECT * FROM ShipPosition sp
LEFT JOIN ShipPosition sp2 ON sp.RelatedShipPositionID = sp2.ShipPositionID
WHERE sp.ShipPositionTypeID IN (11,12)
AND (sp.ModifiedDate BETWEEN '2011-09-09 08:00' AND '2011-09-09 12:00'
OR sp2.ModifiedDate BETWEEN '2011-09-09 08:00' AND '2011-09-09 12:00')
現在、私は NHibernate (3.0) と QueryOver にかなり慣れていないため、この SQL クエリを C# コードに変換するのに少し問題があります。いくつかの例を読み、他の質問を調べてみましたが、残念ながらうまくいきませんでした。
私の最初の試みは次のようなものでした:
public IList<ShipPosition> GetModifiedShipPositions(IList<ShipPositionType> positionTypes, DateTime modifiedFrom, DateTime modifiedTo)
{
var result = Session.QueryOver<ShipPosition>()
.WhereRestrictionOn(p => p.ShipPositionType).IsInG(positionTypes)
.And(Restrictions.Or(
Restrictions.Where<ShipPosition>(p => p.ModifiedDate.IsBetween(modifiedFrom).And(modifiedTo)),
Restrictions.Where<ShipPosition>(p => p.RelatedShipPosition != null
&& p.RelatedShipPosition.ModifiedDate.IsBetween(modifiedFrom).And(modifiedTo))));
return result.List();
}
しかし、これは KeyNotFoundException をスローします (指定されたキーが辞書に存在しませんでした)。私は実験を試みましたが、それは欠けているものの1つであると思われますが、うまくいきませんでしたJoinQueryOver
.JoinAlias
誰かが私を正しい方向に向けることができれば (またはこれがすでに回答されている質問に)、私はとても感謝しています!
アップデート:
私はlinqを使ってクエリを書いてみました:
var query = Session.Query<ShipPosition>().Where(p
=> positionTypes.Contains(p.ShipPositionType)
&& ((p.ModifiedDate > modifiedFrom && p.ModifiedDate < modifiedTo)
|| (p.RelatedShipPosition != null && p.RelatedShipPosition.ModifiedDate > modifiedFrom && p.RelatedShipPosition.ModifiedDate < modifiedTo)));
return query.ToList();
例外はスローされませんでしたが、目的の結果が得られませんでした (p.RelatedShipPosition が null.
言っておきますが、HQL を使用すると問題なく動作し、SQL クエリと同じ結果が得られます。
var queryString = @"
SELECT shipPosition
FROM ShipPosition shipPosition
LEFT JOIN shipPosition.ShipPositionType shipPositionType
LEFT JOIN shipPosition.RelatedShipPosition relatedShipPosition
WHERE shipPositionType.SystemName IN (:positionTypes)
AND (shipPosition.ModifiedDate BETWEEN :modifiedFrom AND :modifiedTo
OR relatedShipPosition.ModifiedDate BETWEEN :modifiedFrom AND :modifiedTo)";
var query = Session.CreateQuery(queryString);
query.SetParameterList("positionTypes", positionTypes.Select(pt => pt.SystemName).ToArray());
query.SetParameter("modifiedFrom", modifiedFrom);
query.SetParameter("modifiedTo", modifiedTo);
return query.List<ShipPosition>();
質問はまだ残っています: どうすればこれを QueryOver の使用に変換できますか?
更新 2:
誰かが興味を持っている場合に備えて、MonkeyCoder の回答の助けを借りて、最終的なコードがどのように見えるかを含めます。
public IList<ShipPosition> GetModifiedShipPositions(DateTime modifiedFrom, DateTime modifiedTo, params ShipPositionType[] positionTypes)
{
ShipPosition relatedShipPosition = null;
var result = Session.QueryOver<ShipPosition>()
.Left.JoinAlias(sp => sp.RelatedShipPosition, () => relatedShipPosition)
.WhereRestrictionOn(sp => sp.ShipPositionType).IsInG(positionTypes)
.And(Restrictions.Or(
Restrictions.Where<ShipPosition>(sp => sp.ModifiedDate.IsBetween(modifiedFrom).And(modifiedTo)),
Restrictions.Where(() => relatedShipPosition.ModifiedDate.IsBetween(modifiedFrom).And(modifiedTo))));
return result.List();
}