在linq中混合数据库和对象查询,并提供分页结果
本文关键字:结果 分页 查询 对象 linq 混合 数据库 | 更新日期: 2023-09-27 18:18:32
我需要构建一个提供分页结果的查询。过滤部分发生在数据库中,部分发生在内存中的对象中。
下面是一个简化的示例,它显示了我可以做什么,即对数据库运行一个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)运行
是否有更好的方法来处理这种情况,而不将初始结果完全加载到内存中
是,在数据库级别查询和页面。Helper中的任何逻辑。MyFilter需要在sql查询中。
是另一个选项,它对代码库的干扰更大。是保存视图模型,以及在实体更改时保存域实体。视图模型的一部分将包含Helper.MyFilter(e)
的结果,因此您可以快速有效地查询它。
为了支持上面Jason的答案-实体框架支持. skip (). take()。因此,将所有数据都发送到db级别,并将您的位置转换为EF可以消费的东西。
如果你的where helper很复杂,可以使用Albahari的谓词构建器:
http://www.albahari.com/nutshell/predicatebuilder.aspx或者更容易使用的通用谓词生成器:
http://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/基于以上。
.ToList()
你正在将你的查询转换为一个内存对象,即列表,从而导致查询执行,然后你提供对数据的分页。
你可以把它们放在一个Where
子句中:
Things.Where(e=>e.field1==1 && e.field2>1
&& e=>Helper.MyFilter(e)).Skip(m*pageSize).Take(pageSize);
,然后是.ToList()
。这样,您将给Linq to Sql一个机会来生成查询,并只获得您想要的数据。
或者有一个特殊的原因为什么你想要这样做-转换到内存对象然后过滤?虽然我不明白这有什么意义。在实际对数据库执行Linq to Sql查询之前,您应该能够过滤掉不想要的结果。
编辑
从讨论中我可以看出你有几个选择。
如果您有很多数据,并且读操作多于写操作,那么在可能的情况下,在插入时将Helper.MyFilter
的结果保存到数据库中可能是明智的。这样可以提高select的性能,因为您不会从数据库中提取所有数据,而且您将在SELECT
本身上拥有更多过滤过的数据。
或者你可以采取另一种方法。您可以将Helper
类放在单独的程序集中,并从SQL Server引用该程序集。这将使您能够将分页逻辑放在数据库中并使用您的代码。