我需要构建一个提供分页结果的查询。部分过滤发生在数据库中,部分过滤发生在内存中的对象中。
下面是一个简化的示例,显示了我可以做什么,即对数据库运行linq查询,然后使用自定义代码进一步过滤它,然后使用skip / take进行分页,但这样做效率非常低,因为它需要加载与查询的第一部分匹配的所有项目。
Things.Where(e=>e.field1==1 && e.field2>1).ToList()
.Where(e=>Helper.MyFilter(e,param1,param2)).Skip(m*pageSize).Take(pageSize);
MyFilter函数使用不在数据库中的其他数据,并使用其他参数运行(上例中的paramX)
是否有一种首选方法可以处理这种情况,而无需将初始结果完全加载到内存中。
答案 0 :(得分:1)
是,在数据库级别查询和页面。 Helper.MyFilter中的任何逻辑都需要在sql查询中。
另一个选项,它对您的代码库更具侵入性。是在实体更改时保存视图模型以及域实体。视图模型的一部分将包含Helper.MyFilter(e)
的结果,因此您可以快速有效地查询它。
答案 1 :(得分:1)
为了支持Jason上面的回答 - 实体框架支持.Skip()。Take()。所以将它们全部发送到数据库级别并将您的位置转换为EF可以使用的内容。
如果你的助手很复杂,请使用Albahari的谓词构建器:
http://www.albahari.com/nutshell/predicatebuilder.aspx
或稍微更容易使用Universal Predicate Builder:
http://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/基于以上内容。
答案 2 :(得分:0)
.ToList()
您正在将查询转换为内存对象,即列表,从而导致查询执行,然后您提供数据分页。
您可以将其全部放在一个Where
子句中:
Things.Where(e=>e.field1==1 && e.field2>1
&& e=>Helper.MyFilter(e)).Skip(m*pageSize).Take(pageSize);
然后.ToList()
。
这样你就可以让Linq给Sql一个生成查询的机会,只获得你想要的数据。
或者有一个特殊的原因,你想要做到这一点 - 转换为内存对象,然后过滤?虽然我没有看到这一点。在对数据库实际执行之前,您应该能够在Linq to Sql查询中过滤掉您不想要的结果。
修改强>
从讨论中我可以看出,你有几种选择。
如果您有大量数据并且执行的读取次数多于写入,那么在可能的情况下将Helper.MyFilter
的结果保存到插入数据库中可能是明智之举。这样,您可以提高select的性能,因为您不会从数据库中提取所有数据,并且您将在SELECT
本身上拥有更多过滤数据。
或者你可以采取另一种方法。您可以将Helper
类放在单独的程序集中reference that assembly from SQL Server。这将使您能够将分页逻辑放入数据库并使用您的代码。