.net 如何在使用存储过程检索的记录上执行ToList()之前的Count()?

bvuwiixz  于 2023-03-09  发布在  .NET
关注(0)|答案(1)|浏览(99)

下面是我的代码:

// grid query
var data = ctx.spRewards(Month, Year, null, MedicalID).Select(p => new
{
    MedicalID = p.MedicalID,
    DateReward = p.DateReward,
    Medical = p.Medical,
    AmountRefunds = p.AmountRefunds,
    AmountActivitiesStart = p.AmountActivitiesStart,
    AmountActivitiesEnd = p.AmountActivitiesEnd,
    AmountActivities = p.AmountActivities,
    AmountTotal = p.AmountTotal,
    Month = p.Month,
    Year = p.Year
});

// some further filters that will be attached in case

// grid order
data = data.OrderBy(p => p.DateReward).ThenBy(p => p.MedicalID);

// grid data
var dataTotal = data.Count();
if (formData.length >= 0)
{
    data = data.Skip(formData.start).Take(formData.length);
}
var dataFiltered = data.ToList();
return Json(new { data = dataFiltered, recordsFiltered = dataTotal, recordsTotal = dataTotal });

但是,一旦我尝试执行var dataFiltered = data.ToList();,我就会得到一个 * 查询的结果不能被枚举多次 *。
我的意图是首先只返回记录的计数(为了只获得过滤后的数据量,而不下载内存中的所有记录,然后返回Count,这将花费时间和资源),然后使用Skip/Take对其进行分页。
通常,在表上使用IQueryable<a>可以实现此功能:

var data = ctx.SomeTable.AsNoTracking().Select(p => new
{
    //
})

但它不能直接调用DB中的存储过程。我尝试过将dataIEnumerable<a>转换为IQueryable<a>,但我得到了同样的错误。
我需要配置什么?

z18hc3ub

z18hc3ub1#

我认为您的问题在于您使用的是带有实体框架的存储过程,它创建了一个只向前的结果集。
使用扩展方法,可以创建具有相同条件的新查询:

public static class IQueryableExt {
    public static IQueryable<T> CloneQuery<T>(this IQueryable<T> q) => q.Provider.CreateQuery<T>(q.Expression);
}

然后,您可以对总计数使用原始查询,对筛选的记录使用克隆查询:

// grid data
var data2 = data.CloneQuery();
var dataTotal = data.Count();
if (formData.length >= 0)
{
    data2 = data2.Skip(formData.start).Take(formData.length);
}
var dataFiltered = data2.ToList();

相关问题