0

私が取り組んでいるプロジェクトでは、NHibernate をバックエンドとして使用するリポジトリに仕様 (Martin Fowler によって提唱された仕様パターン) を渡しています。特定のオブジェクトが式としてラップされたラムダとして実装されているかどうかを判断するための述語。リポジトリはこれを NHibernate の Criteria API に渡し、実際に結果をフェッチします。

私たちが持っているものは次のようになります:

class MySpecification : ISpecification<AnEntity>
{
      public Expression<Func<AnEntity, bool>> Satisfies
      {
           get { return entity => entity.Children.Count(c => !c.IsDeleted) == 0; }
      }
}

そしてリポジトリで:

public IEnumerable<AnEntity> Select(ISpecification<AnEntity> spec)
{
      ICriteria criteria = Session.CreateCriteria<AnEntity>();
      criteria.Add(NHibernate.Criterion.Expression.Where(spec.Satisfies));
      return criteria.List<AnEntity>();
}

実行時に、次の形式の例外を受け取ります。

{variable 'entity' of type 'AnEntity' referenced from scope '', but it is not defined"} System.Exception {System.InvalidOperationException}

述語を、子コレクションに対してセット操作 (Any、Count、Where など) を実行しない単純なブール式に減らすと、すべてが正常に機能します。

それを念頭に置いて、メイン エンティティの子コレクションで動作するラムダ式を使用して基準を構築する方法はありますか?

4

1 に答える 1

1

Criteria API ではそのようなことはできません。Linq と Criteria API を混在させようとしています。Criteria API には、子コレクションを操作するための独自のメソッドがあります。

linq-to-nhibernate を使用して、目的を達成できます。次のようにメソッドを変更してみてください

public IEnumerable<AnEntity> Select(ISpecification<AnEntity> spec)
{
    return Session.Query<AnEntity>() 
        .Where(spec.Satisfies)
        .ToList();
}

Query拡張メソッドですNHibernate.Linq.LinqExtensionMethods.Query(this ISession session)

于 2012-08-01T18:40:31.463 に答える