在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)运行

是否有更好的方法来处理这种情况,而不将初始结果完全加载到内存中

在linq中混合数据库和对象查询,并提供分页结果

是,在数据库级别查询和页面。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引用该程序集。这将使您能够将分页逻辑放在数据库中并使用您的代码。