1

2つのテーブル(Orders、Transactions)と、OrderId列とTransactionsId列だけを保持するTransactionsOrdersルックアップテーブルがあります。

トランザクションが(n)回失敗した場合、1つの注文に対して複数のトランザクションが存在する可能性があります。また、Orderオブジェクトにはトランザクションに関する知識がありません。

成功したトランザクションレコードがその注文に存在する場合、すべての注文プロパティと、トランザクションテーブルから2つのプロパティ(AmountとTransactionDate)を返す必要があるため、予測を使用する必要があると思います。以下は、正しい出力を生成するSQLです。

   SELECT o.*, ct.TransactionDate, ct.Amount from Orders o
   LEFT OUTER JOIN 
     (SELECT * FROM CreditTransactionsOrders cto
          INNER JOIN CreditTransactions ct 
      ON ct.Id = cto.CreditTransactionId
      WHERE ct.Successful = 1) as ct 
   ON o.Id = ct.OrderId

このQueryOverを作成し、OrderオブジェクトとTransactionオブジェクトから必要なプロパティを投影しようとしましたが、このSQLクエリを適切に変換できません。

最終結果は、すべての注文を返す必要があり、その注文に成功したものが存在する場合は、トランザクションオブジェクトから金額と日付を返す必要があります。エイリアスを使用する必要があるかどうかはよくわかりませんが、これまでのところ、すべての試みは失敗しています。

4

1 に答える 1

2

まず、SQLをよりNHibernateに適した状態に書き直す必要があります。

SELECT o.*, ct.TransactionDate, ct.Amount from Orders o
  LEFT OUTER JOIN CreditTransactionsOrders cto 
    ON o.Id = cto.OrderId
  LEFT OUTER JOIN CreditTransactions ct 
    ON ct.Id = cto.CreditTransactionId AND ct.Successful = 1

このSQLは、元のクエリと同じ結果を生成します。

withNHibernateでは、参加の追加基準をステートメントとして変換できます。

withClauseしたがって、オーバーロード受け入れ引数を使用できます。したがって、OrdersとCreditTransactionsが多対多としてマップされていると仮定します。次のQueryOverを取得する必要があります。

Order o = null;
CreditTransaction ct = null;

var orders = session.QueryOver(() => o)
    .Left.JoinAlias(x => x.Transactions, () => ct, () => ct.Successful == 1)
    .List<Order>();

アップデート

Orderからへの参照がないTransactionため、結合を元に戻す必要があります。これにより、右結合を使用してこれを実現できます。

Order o = null;
CreditTransaction ct = null;

var orders = session.QueryOver(() => ct)
    .Right.JoinAlias(x => x.Orders, () => o, () => ct.Successful == 1)
    .Select(
        x => x.TransactionDate,
        x => x.Amount,
        x => o.Id // other Order fields
    ).TransformUsing(Transformers.AliasToBean<TransactionsDto>())
    .List<TransactionsDto>();

TransactionsDtoクラスには、選択したすべてのフィールドが含まれている必要があります。

于 2012-07-23T16:04:21.230 に答える