2

在过去的几个月里,我一直在使用 Linq to 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;
    }

它似乎首先运行初始存储库查询,然后遍历所有结果检查以查看 CompletionDate 是否为空,但首先发出查询以获取 c.Property.Address。

因此,如果初始查询返回 2,000 条记录,即使其中只有 5 条没有 CompletionDate,它仍会触发 SQL 查询以返回 2,000 条记录的地址详细信息。

我想象这会起作用的方式是,它将评估所有 WHERE 和 SELECT 子句并简单地将它们合并,因此初始查询将如下所示:

SELECT ... WHERE ProjectManager = @p1 AND CompleteDate 不为空

这将产生 5 条记录,然后它可以触发进一步的 5 次查询以获取地址。我在这里期待太多,还是我只是做错了什么?

安东尼

4

2 回答 2

6

更改 GetCasesByProjectManagerID 的声明:

public IQueryable<Case> GetCasesByProjectManagerID(int projectManagerId)

您不能使用IEnumerable<T>- 它们只是序列来编写查询。IQueryable<T>是专门为这样的组合而设计的。

于 2009-07-22T16:09:36.210 回答
0

因为我还不能添加评论。Jon Skeet 是对的,你会想要使用 IQueryable,这允许 Linq 提供者懒惰地构造 SQL。IEnumerable 是急切的版本。

于 2009-07-22T16:15:28.570 回答