将谓词中的操作设置传递给NHibernate的Criteria API

时间:2012-08-01 18:05:49

标签: c# nhibernate criteria specifications

在我正在开发的项目中,我们将一个规范(由Martin Fowler提出的规范模式)传递给使用NHibernate作为其后端的存储库。用于确定给定对象是否实现为包含为表达式的lambda的谓词,存储库将其移交给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)的简单布尔表达式时,一切正常。

考虑到这一点,有没有办法使用lambda表达式构建一个标准,该表达式对主实体的子集合进行操作?

1 个答案:

答案 0 :(得分: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)