0

NHibernate v3.2.0 と次のクエリに問題があります。

class DocumentBase {}
class Requisition: DocumentBase {}
class Order: DocumentBase {}

Repository.GetAll<DocumentBase>()
    .Where(d => (d is Requisition) && ((Requisition)d).ProductItem != null)

基本クエリはすべてのドキュメントを一覧表示するように設計されていますが、このドキュメントをタイプ (および製品のないドキュメントなどの準タイプ) でフィルタリングすることもできます。上記のコードには条件が 1 つしかありませんが、述語はより複雑になる可能性があります。たとえば、次のようになります。

Repository.GetAll<DocumentBase>()
    .Where(d => 
        ((d is Requisition) && ((Requisition)d).ProductItem != null) ||
        (d is Order) ||
        [...]
    )

InvalidPathException実行すると、メッセージで受け取りますInvalid path: 'd.ProductItem'。何か案は?サポートされていますか?

これまでのところ、次のクエリでこのエラーを回避できました。

Repository.GetAll<DocumentBase>()
    .Where(d => 
        (d is Requisition) &&
        Repository.GetAll<Requisition>()
            .Any(r => r.Id == d.Id && r.ProductItem != null)
    )

しかし、間違いなく、パフォーマンスの点で最良の選択ではありません。

4

2 に答える 2

2

Repository.GetAll<T>あなたのメソッドはを返していると思いますsession.Query<T>Where句を持つことができる式のサブセットは限られています。NHibernateは、Where式をHQLに変換し、最終的にはSQLに変換しようとします。これは、Whereに何も記述できず、それが機能することを期待できないことを意味しますが、変換が存在する式のみを記述します。ただし、NHibernateのLinqプロバイダーは拡張できます。

あなたのケースは単純化することができます。サブクラスをマッピングしている場合...おそらくそうしている場合、クエリは次のように記述できます。

Repository.GetAll<Requisition>().Where(r => r.ProductItem != null);
于 2012-08-08T08:47:33.980 に答える
0

誰かが言及したように、NHibernate で Linq プロバイダーを拡張することは可能です。これが私のために働いた解決策です:

public static class OzirNhExtensions
{
    // Cast method to use in query
    public static TTarget Cast<TTarget>(this Object source)
    {
        return ((TTarget)source);
    }
}

class CastHqlGeneratorForMethod : BaseHqlGeneratorForMethod
{
    public CastHqlGeneratorForMethod()
    {
        this.SupportedMethods = new MethodInfo[] {
            ReflectionHelper.GetMethodDefinition(
                () => OzirNhExtensions.Cast<Object>(null)
            )
        };
    }

    // In here simply skip cast expression 
    // (it works probably because I have every sub-entity 
    // in the same table that base entity)
    public override HqlTreeNode BuildHql(
        MethodInfo method, 
        Expression targetObject, 
        ReadOnlyCollection<Expression> arguments, 
        HqlTreeBuilder treeBuilder,
        IHqlExpressionVisitor visitor)
    {
        return visitor.Visit(arguments[0]).AsExpression();
    }
}

クエリの例:

Repository.GetAll<DocumentBase>()
    .Where(d => d.Cast<Requisition>().ProductItem != null && 
        d.Cast<Requisition>().ProductItem.Name == "Something"
    )
于 2012-09-13T21:18:18.833 に答える