You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Entity Framework Core中异步执行带结果集的存储过程

异步调用存储过程获取报表结果的问题解决

我创建了一个生成报表的存储过程,包含Id、UserName、NumOfSomething、Month这些标准字段。目前已实现同步获取结果的版本:

public async ValueTask<List<ReportDto>> GetReport(int managerId)
{
    var result = reportContext.Database.SqlQuery<ReportDto>($"MonthlyNumOfCasesPerUserReport @ManagerId = {managerId}").ToList();

    return result;
}

这段代码能将存储过程结果映射到ReportDto实体类,但尝试改用ToListAsync()实现异步时,触发了以下错误:

System.InvalidOperationException: 源IQueryable未实现IDbAsyncEnumerable<CommonLibrary.Dto.ReportDto>。只有实现IDbAsyncEnumerable的数据源才能用于Entity Framework异步操作。


错误原因

当前查询返回的IQueryable对象没有实现EF异步操作依赖的IDbAsyncEnumerable接口,这通常是因为查询方式未正确适配EF的异步支持,同时原代码的字符串拼接参数方式还存在SQL注入风险。

解决方案

针对EF6的实现

确保引用System.Data.Entity命名空间,使用参数化查询并调用EF提供的异步扩展方法:

using System.Data.Entity;

public async ValueTask<List<ReportDto>> GetReport(int managerId)
{
    var result = await reportContext.Database
        .SqlQuery<ReportDto>("MonthlyNumOfCasesPerUserReport @ManagerId", new SqlParameter("@ManagerId", managerId))
        .ToListAsync();

    return result;
}

针对EF Core的实现

EF Core中Database.SqlQuery已被弃用,需先在DbContext中声明对应DbSet,再使用FromSqlRaw执行异步查询:

  1. 在DbContext中添加DbSet:
public DbSet<ReportDto> ReportDtos { get; set; }
  1. 修改异步查询方法:
using Microsoft.EntityFrameworkCore;

public async ValueTask<List<ReportDto>> GetReport(int managerId)
{
    var result = await reportContext.ReportDtos
        .FromSqlRaw("EXEC MonthlyNumOfCasesPerUserReport @ManagerId = {0}", managerId)
        .ToListAsync();

    return result;
}

内容的提问来源于stack exchange,提问作者zchpit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 09:33:20