5

私の現在のプロジェクトでは、NHibernate 3.0b1 とNHibernate.Linq.Query<T>()API を使用しています。私は LINQ にはかなり精通していますが、HQL や ICriteria API の経験はまったくありません。私のクエリの 1 つが IQueryable API でサポートされていないため、以前の API のいずれかを使用する必要があると思いますが、どこから始めればよいかわかりません。

ICriteria の優れた「入門」ガイドを Web で検索してみましたが、ここで適用するには単純すぎるか、高度すぎて理解できない例しか見つかりませんでした。良い教材をお持ちの方がいらっしゃいましたら、よろしくお願いいたします。

いずれにせよ、クエリを実行しているオブジェクト モデルは次のようになります (大幅に簡略化され、関連性のないプロパティは省略されています)。

class Ticket {
    IEnumerable<TicketAction> Actions { get; set; }
}
abstract class TicketAction {
    Person TakenBy { get; set; }
    DateTime Timestamp { get; set; }
}
class CreateAction : TicketAction {}
class Person {
    string Name { get; set; }
}

Aには、その歴史Ticketを説明するコレクションがあります。サブタイプには、、などが含まれます。すべてのチケットは、作成時にこのコレクションに追加されます。TicketActionTicketActionCreateActionReassignActionCloseActionCreateAction

この LINQ クエリは、特定の名前を持つ人物によって作成されたチケットを検索しています。

var createdByName = "john".ToUpper();
var tickets = _session.Query<Ticket>()
    .Where(t => t.Actions
        .OfType<CreateAction>()
        .Any(a => a.TakenBy.Name.ToUpper().Contains(createdByName));

このOfType<T>()メソッドにより、 aNotSupportedExceptionがスローされます。代わりに ICriteria を使用してこれを行うことはできますか?

4

2 に答える 2

2

このようなことを試してください。コンパイルされていませんが、nullIEnumerable<TicketAction> Actionsである限り機能するはずです。Person TakenByチケットコンストラクターで空のリストに設定すると、nullの問題が解決されます。

TicketActionでTicketオブジェクトへの参照を追加すると、次のようになります。

ICriteria criteria = _session.CreateCriteria(typeof(CreateAction))
   .Add(Expression.Eq("TakenBy.Name", createdByName));

var actions = criteria.List<CreateAction>();

var results = from a in criteria.List<>()
   select a.Ticket;

私の経験では、リストがオブジェクト側にある場合、nhibernateはリストに関して基準に問題があります(あなたの場合など)。入力側の値の一覧の場合は、Expression.Eqを使用できます。私は常にlinqを介してこの制限を回避する方法を見つける必要がありました。ここでは、最初の結果セットを可能な限りフィルタリングして取得し、次にlinqで再度フィルタリングして必要なものを取得します。

于 2010-11-01T14:10:18.890 に答える
0

OfType がサポートされています。ToUpper かどうかはわかりませんが、SQL は大文字と小文字を区別しないので問題ありません (メモリ内でクエリを実行していない限り...)。nHibernate.LINQ プロジェクトの作業単体テストを次に示します。

var animals = (from animal in session.Linq<Animal>()
               where animal.Children.OfType<Mammal>().Any(m => m.Pregnant)
               select animal).ToArray();
Assert.AreEqual("789", animals.Single().SerialNumber);

おそらく、クエリは次のようになります。

var animals = (from ticket in session.Linq<Ticket>()
               where ticket.Actions.OfType<CreateAction>().Any(m => m.TakenBy.Name.Contains("john"))
               select ticket).ToArray();
于 2010-11-03T07:45:39.370 に答える