理论上我有两个类似的查询返回相同的结果:
var requestNotWorking = SessionManagement.Db.Linq<Item>(false).Where(i =>
i.Group != null && i.Group.Id == methodParameter)
.ToList();
此请求返回0项,即使它应该返回一项。
以下是对后者的重写,但调用了ToList()
方法。此请求有效并返回第一个查询中预期的项目!
var requestWorking = SessionManagement.Db.Linq<Item>(false).ToList().Where(i =>
i.Group != null && i.Group.Id == methodParameter).ToList();
注意:SessionManagement.Db.Linq<Item>(false)
是一个通用的Linq to Nhibernate方法,其布尔属性确定请求是否必须在缓存(true)或数据库(false)中执行。这种方法应该没有错,因为它在解决方案的许多其他部分正常工作。 Item的映射没什么特别之处:没有包包和以下参数:
lazy="false" schema="dbo" mutable="false" polymorphism="explicit"
为什么会这样?
修改:
生成的requestNoWorking的sql请求以:
结束 (Item.Group_ID is not null) and Item.Group_ID=@p0',N'@p0 int',@p0=11768
生成的requestWorking的sql请求大致为select * from dbo.Items
答案 0 :(得分:4)
我假设你在那里进行的nhibernate会话返回一个可查询的东西。如果是这样,则第一个查询的评估将延迟到.ToList()
调用,并且整个查询将在服务器上运行。我建议你尽可能在sql服务器上运行一个跟踪,或者下载NHProf以查看正在执行的实际查询是什么。
第二个查询在您点击第一个.ToList()
后立即进行评估,因此您将整个表从数据库中拉回来,然后使用.net进行过滤。老实说,我不能告诉你为什么他们会以不同的方式进行评估,但我认为有一些映射/配置导致db查询写得有点错误。
答案 1 :(得分:1)
我对c.Group.Id != null
的理论非常感兴趣,虽然它与我解决方案中的其他代码段相矛盾,但我发现它是合乎逻辑的。但是,删除它并没有改变任何东西。我发现删除mutable="false"
属性解决了这个问题。这看起来有点神奇,但确实有效。
我发布的请求实际上发生在检查更新/删除可能性的方法中。我的结论是,以某种方式使Item immutable导致结果失败。但我不明白为什么requestWorking工作呢!
答案 2 :(得分:0)
我只能看到,在第二个版本中,你的Where
由LINQ to Objects而不是LINQ to NHibernate执行。所以第一个版本必须做一些LINQ to NHibernate不能很好地消化的东西。
我思考这是LINQ To NHibernate遇到问题的i.Group != null
,看到null
的使用是特定于CLR的。您可能需要在LINQ to NHibernate中使用另一个构造来测试空字段值。