过去几个月我一直在使用Linq到NHibernate开发一个webapp,但是直到现在还没有描述它生成的SQL。使用NH Profiler,现在看来,当执行Linq表达式时,下面的代码块会使DB超过3,000次。
var activeCaseList = from c in UserRepository.GetCasesByProjectManagerID(consultantId)
where c.CompletionDate == null
select new { c.PropertyID, c.Reference, c.Property.Address, DaysOld = DateTime.Now.Subtract(c.CreationDate).Days, JobValue = String.Format("£{0:0,0}", c.JobValue), c.CurrentStatus };
Repository方法的样子:
public IEnumerable<Case> GetCasesByProjectManagerID(int projectManagerId)
{
return from c in Session.Linq<Case>()
where c.ProjectManagerID == projectManagerId
select c;
}
它似乎首先运行初始Repository查询,然后遍历所有结果检查以查看CompletionDate是否为null,但是发出查询以首先获取c.Property.Address。
因此,如果初始查询返回2,000条记录,即使其中只有五条没有CompletionDate,它仍然会触发SQL查询以恢复2,000条记录的地址详细信息。
我想象的方式可行,是它会评估所有WHERE和SELECT子句并简单地合并它们,因此初始查询将如下:
SELECT ... WHERE ProjectManager = @ p1 AND CompleteDate IS NOT NULL
哪个会产生5条记录,然后它可以触发另外5条查询以获取地址。我在这里期待太多,或者我只是做错了什么?
安东尼
答案 0 :(得分:6)
更改GetCasesByProjectManagerID的声明:
public IQueryable<Case> GetCasesByProjectManagerID(int projectManagerId)
您无法使用IEnumerable<T>
撰写查询 - 它们只是序列。 IQueryable<T>
专为此类作文设计。
答案 1 :(得分:0)
由于我还不能添加评论。 Jon Skeet是对的,你想要使用IQueryable,这是允许Linq提供者来Lazily构造SQL。 IEnumerable是渴望的版本。