NHibernate集合Count()进退两难

时间:2011-06-28 21:44:59

标签: c# nhibernate

我通常在我的应用程序中使用“Page - > Service - > Repository”模式,将所有数据库调用放在“repository”类中。

在某些情况下,我要在我的服务逻辑中测试收集项目数。

示例:

EventService eventService=container.Resolve<EventService>();
IEnumerable<Event> events=eventService.GetAll();
if(events.Count()>0)
{
    ...do something...
}

使用NHibernate,这将自动生成一个带有数据库访问权限的SQL语句。

我可以避免这个吗?有最好的做法吗?

2 个答案:

答案 0 :(得分:4)

我尝试避免在存储库中公开IQueryable<T>,原因如下:

  • 支持或不支持许多方法,并不总是清楚会生成什么类型​​的查询。
  • 支持即席查询破坏了为特定用例设计适当索引的重要性。
  • 您将失去预期的查询类型的规范。

相反,我会选择使用一个简单的查询对象,该对象被翻译成存储库所需的任何内容。

特别是对于这种情况,我会在存储库上有一个返回分页事件列表的方法:

IList<Event> GetAll(int startIndex, int count);

这也凸显了分页的重要性。在存储库中,这可能是:

this.Session.Linq<Event>().Skip(startIndex).Take(count).ToList();

您也可以选择为IList创建一个包装对象,它也可以包含总计数。

答案 1 :(得分:1)

如果您(单位)测试您的服务层,那么您应该嘲笑您的存储库。您可以创建一个模拟存储库,其中包含作为IQueryable公开的静态对象列表。

这样当你调用Count()时,它将返回静态列表的计数,你可以可靠地断言。

更新

我的错误,我从这一行开始假设

  

我要测试收集物品的数量   我的服务逻辑

你想测试你的服务逻辑。

您的上述代码看起来像是在返回IQueryable。因此,只要您调用Count()ToList()(基本上是枚举IQueryable的任何内容),您就会点击数据库。

因此,请更改您的服务以返回IList<T>或将您的代码更改为以下内容:

EventService eventService=container.Resolve<EventService>(); 
IEnumerable<Event> events = eventService.GetAll().ToList(); 
if(events.Count()>0) {     ...do something... } 

当您致电ToList()时,您将点击数据库,但在使用内存中集合时调用Count()时则不会。