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

ASP.NET Core 6 Minimal API访问SQL Server时遇DataReader已打开错误

解决“已有打开的DataReader关联此连接,必须先关闭”错误

问题根源

你在查询Inquiry的投影逻辑(select new Inquiry)里直接调用了GetLocationById方法,而这个方法又用同一个CCTPDbContext发起了新的数据库查询。此时第一个db.Inquiry的查询还在执行(EF Core默认延迟执行,枚举结果时才会真正访问数据库),导致同一个数据库连接上同时有两个DataReader在运行——SQL Server默认不允许这种情况,因此抛出错误。

你之前尝试的Dispose和using语句无效,是因为你错误地复用了已有的DbContext实例,而非解决“同时执行多个查询”的核心问题。

解决方案

方案1:先加载基础数据到内存,再查询关联数据

先把Inquiry的基础数据完整查询出来并加载到内存,确保第一个数据库查询完成后,再调用GetLocationById获取关联的Location:

修改Program.cs中的端点代码:

app.MapGet("/Inquiry/test/{InquiyId}", async (CCTPDbContext db, HttpRequest request) =>
{
    int InquiryId = Int32.Parse(request.RouteValues["InquiyId"].ToString());

    // 先查询并加载Inquiry数据到内存
    var inquiryFromDb = await db.Inquiry.FirstOrDefaultAsync(i => i.Id == InquiryId);

    if (inquiryFromDb == null)
    {
        return Results.NotFound();
    }

    // 此时第一个查询已完成,连接已释放,再调用GetLocationById
    var inquiryZ = new Inquiry
    {
        Id = inquiryFromDb.Id,
        LocationId = inquiryFromDb.LocationId,
        Description = inquiryFromDb.Description,
        DateFrom = inquiryFromDb.DateFrom,
        DateTo = inquiryFromDb.DateTo,
        LocationLautLocationId = new Location().GetLocationById(db, inquiryFromDb.LocationId),
        // 其他属性赋值...
    };

    return Results.Ok(inquiryZ);
});

方案2:使用EF Core导航属性(推荐)

如果Inquiry实体中已经定义了到Location的导航属性(这是EF Core的最佳实践),可以直接用Include进行关联查询,一次数据库请求就能获取所有需要的数据,从根源避免多DataReader问题:

  1. 确保Inquiry实体包含导航属性:
public class Inquiry
{
    // 现有属性...
    public int LocationId { get; set; }
    public Location? LocationLautLocationId { get; set; } // 导航属性
}
  1. 修改端点查询代码:
app.MapGet("/Inquiry/test/{InquiyId}", async (CCTPDbContext db, HttpRequest request) =>
{
    int InquiryId = Int32.Parse(request.RouteValues["InquiyId"].ToString());

    var inquiryZ = await db.Inquiry
        .Include(i => i.LocationLautLocationId) // 关联查询Location表
        .Where(i => i.Id == InquiryId)
        .Select(i => new Inquiry
        {
            Id = i.Id,
            LocationId = i.LocationId,
            Description = i.Description,
            DateFrom = i.DateFrom,
            DateTo = i.DateTo,
            LocationLautLocationId = i.LocationLautLocationId,
            // 其他属性...
        })
        .FirstOrDefaultAsync();

    if (inquiryZ == null)
    {
        return Results.NotFound();
    }

    return Results.Ok(inquiryZ);
});

这种方式不仅解决了错误,还减少了数据库请求次数,性能更优。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 01:58:16