如何在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执行异步查询:
- 在DbContext中添加DbSet:
public DbSet<ReportDto> ReportDtos { get; set; }
- 修改异步查询方法:
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
相关产品推荐
相关产品推荐

