如何从分页 ef core 查询获取总可用行数

问题描述 投票:0回答:4

预先感谢您花时间阅读此问题。

我的数据库中有一个视图,我们称之为 Members_VW

在我的 .net 5 API 中,我尝试使用搜索参数从视图中获取成员列表的分页响应。我还需要返回前端的响应总数,以了解结果将在多少页中返回。

目前 Members_VW 是通过如下查询创建的:

select
    col1, col2, col3
from
    table1 1
    inner join table2 2 on 1.key = 2.key
    inner join tble3 3 on 3.key = 2.key
where
    defaultcondition1 = '1'
        and
    defaultcondition2 = '2'

我提到了this答案并尝试使用CTE,最终将我的视图更改为使用这样的查询:

with cte1 as (
select
    col1, col2, col3
from
    table1 1
    inner join table2 2 on 1.key = 2.key
    inner join tble3 3 on 3.key = 2.key
where
    defaultcondition1 = '1'
        and
    defaultcondition2 = '2')
cte2 as (
select count(*) over() from cte1 )
select
    *
from
    cte1, cte2

但这不起作用,因为它总是返回

cte1
中的总行数,而不应用任何过滤器。

于是,我继续尝试构造查询以返回应用条件后的总行数,发现这个查询有效:

select
    col1, col2, col3, count(*) over()
from
    table1 1
    inner join table2 2 on 1.key = 2.key
    inner join tble3 3 on 3.key = 2.key
where
    defaultcondition1 = '1'
        and
    defaultcondition2 = '2'

目前,我正在尝试使用 EF Core 实现相同的查询,但很难实现。

我已经尝试实现here提供的解决方案,但正如其中一条评论所暗示的那样,这种实现不再被允许。

我试图避免使用原始查询的实现。有没有办法在不使用原始查询的情况下从

count(*) over()
获取结果?

以下是我当前的实现:

IQueryable<MembersVW> membersQuery = _context.MembersVW;
membersQuery = membersQuery.Where(u => u.MemberId == memberid);
membersQuery = membersQuery.OrderBy(m => m.MemberId).Skip(page * size).Take(size);

当我这样做时:

membersQuery = membersQuery.Count()
我返回时出现以下错误:

Error   CS0029  Cannot implicitly convert type 'int' to 'System.Linq.IQueryable<PersonalPolicyAPI.Models.VwPersonalPolicyMember>'

再次感谢您阅读我的问题,感谢您提供的任何帮助。 🙏🏾

c# .net-core entity-framework-core .net-5 ef-core-5.0
4个回答
3
投票

我已阅读您关于是否可以通过一个查询完成的问题。虽然我不知道有什么方法可以使用 1 个查询来完成此操作,但我可以提供另一种解决方案,该解决方案将帮助您解决对性能和 2 个查询的担忧。我经常这样做。 😁 尝试:

//execute both queries at the same time instead of sequentially
//assuming _context exists and you know how to new up a new instance
var ctxt2 = new MembersContext();

var countqry = _context.Members.CountAsync();
var pageqry = ctxt2.Members.OrderBy(m=>m.MemberId).Skip(page*size).Take(size).ToListArray();

//wait for them both to complete
Task.WaitAll(countqry, pageqry);

//use the results
var count = countqry.Result;
var page = pageqry.Result;

2
投票

您尝试将计数值(整数)分配给查询变量(IQueryable)。这就是全部内容了。

如果您想在单个查询中执行此操作,正如您在评论中建议的那样,您可以首先执行查询以获取所有条目,然后对结果进行计数,然后使用skip/take 过滤结果。这很可能不是最有效的方法,但它应该有效。

如果您不修改此函数/api 中的任何数据,我还建议使用 AsNoTracking()。

编辑: 我现在建议这个解决方案。计数速度很快,因为它实际上不获取任何数据,只是计算行数。不过,这仍然是两个问题,我会尝试将其合并并稍后编辑我的答案。

 var count = await yourContext.YourTable.CountAsync();
 var data = await yourContext.YourTable
    .OrderBy(x => x.YourProp)
    .Skip(10).Take(10)
    //.AsNoTracking()
    .ToListAsync();

编辑2: 好吧,所以,我还不能让它只在 DB-Call 上进行,但是,我可以在语法上将它组合起来。然而,我第一次编辑的方法更容易阅读并且基本相同。尽管如此,要更深入地研究这个问题,必须有一种时髦的方法来做到这一点。

var query = yourContext.YourTable.AsQueryable();
var result =  await query.OrderBy(x => x.Prop)
                .Select(x => new {Data = x, Count = query.Count()} )
                .Skip(50).Take(50)
                .AsNoTracking()
                .ToListAsync();
var count = result.FirstOrDefault()?.Count ?? 0; //If empty/null return 0
var data = result.Select(x => x.Data).ToList();


1
投票

membersQuery = membersQuery.Count()
行中,您将整数值分配给可查询列表,这是不正确的。您可以在查询后获取列表项计数,如下所示

membersQuery = membersQuery.OrderBy(m => m.MemberId).Skip(page * size).Take(size);
int totalCount = membersQuery.Count();

要在同一列表中获取计数列,您首先需要在 MembersVW 类中添加 Count 属性,然后使用 LINQ 投影添加列值。

解决方案-1:

memberQuery = membersQuery.Select(p => new MembersVW 
              {
                  col1 = p.col1
                  col2 = p.col2
                  col3 = p.col3
                  count = totalCount
              });

解决方案2:

使用 LINQ foreach 循环,即

membersQuery.ForEach(item => 
              {
                  item.count = totalCount;
              });

0
投票

membersQuery.Count() 返回整数而不是可查询的

你可以做

     int count = membersQuery.Count();
     List<MemberVW> = membersQuery.OrderBy(m => m.MemberId).Skip(page * size).Take(size).ToList();

你可以用

返回
       public class MemberVwWithCount {
           public int Count{get;set;}
           public List<MemberVW> Members {get; set;}
         }
© www.soinside.com 2019 - 2024. All rights reserved.