2

NHibernate データ アクセス用の汎用リポジトリを作成しようとしています。メソッドはGet<T>()、オプションの述語を取得できる必要があり、クエリに含める必要があります。つまり、NHibernate は SQL で WHERE 句を生成する必要があります。

    public virtual IList<T> Get(Func<T, bool> predicate = null)
    {
        // Open NHibernate Session
        using (var session = NHibernateHelper.OpenSession())
            return (predicate != null
                       ? session.Query<T>().Where(predicate)
                       : session.Query<T>()).ToList();

    }

述語を渡し、NH が生成する SQL ステートメントを観察すると、where 句が表示されません。

NHibernate はいつクエリを実行しますか? 電話するときは.Query<T>()?もしそうなら、どうすればこれを達成できますか?

4

2 に答える 2

5

クエリは、呼び出しによって実行する必要がありますToList()

SQL ステートメントに WHERE 句が含まれていないのはExpression<Func<T,bool>>、メソッドに を渡す必要がある場合です。

public virtual IList<T> Get(Expression<Func<T, bool>> predicate = null)
    {
        // Open NHibernate Session
        using (var session = NHibernateHelper.OpenSession())
            return (predicate != null
                       ? session.Query<T>().Where(predicate)
                       : session.Query<T>()).ToList();

    }

拡張メソッドはEnumerableWhere(Func<T,bool>>)で定義されているため、クエリはすべてのデータを読み込み、メモリ内の WHERE フィルターを適用します。

拡張メソッドはQueryableWhere(Expression<Func<T,bool>>)で定義されているため、クエリ プロバイダー (NHibernate) は、データ ソースで実行される WHERE 条件を含む SQL ステートメントを作成できます。

于 2013-03-22T08:56:56.367 に答える
1

@Jehofが正しい説明をしてくれたので、別のメモを追加したいだけです-IList<T>他のlinq操作はデータベースではなくメモリで実行されるため、リポジトリメソッドから戻るべきではありません。次の呼び出しを想定

var data = repository.Get<Company>(c=>c.Name.StartsWith("MyCompany"));
... some other operations / method calls etc.
var companySubset = data.Where(...);

そのため、IList<T> Get<T>()パフォーマンスが低下しIQueryable<T> Get<T>ても、データベース クエリに 2 番目の Where() が追加されたままになる場合があります。

もちろん、すべての linq 操作がIQueryablelike (join , last ) によってサポートされているわけではありません。これは、ToList()エクステンションを呼び出して式を評価する唯一の場所です。

于 2013-03-22T09:21:44.683 に答える