masastack / MASA.Framework

.NET next-generation microservice development framework, which provides cloud native best practices based on Dapr.
https://docs.masastack.com/framework/getting-started/overview
MIT License
713 stars 113 forks source link

minimalAPI调用EFcore的生命周期异常 #687

Closed raokun closed 6 months ago

raokun commented 9 months ago

Description

现象

使用minimalapi +EFcore+postgresql 开发的接口,在前端出现同时调用后端接口时报错,dbcontext使用异常。将项目改成MVC的controller后调用接口正常。

期望

对应的依赖注入都是scope,dbcontext的生命周期应该是在一次接口调用时,而其他接口应该在调用时使用新的dbcontext,不应该出现DbContext重复访问的现象。

配置(依赖注入代码)

builder.Services.AddScoped<IAnalysisService, AnalysisService>();
//数据库
builder.Services.AddDbContext<FrameworkDbContext>(opt =>
{
    var connStr = dbConnStr;
    opt.UseNpgsql(connStr);
    //设置EF默认AsNoTracking,EF Core不 跟踪
    opt.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
    if(isDev)
    {
        //启用此选项后,EF Core将在日志中包含敏感数据,例如实体的属性值。这对于调试和排查问题非常有用。
        opt.EnableSensitiveDataLogging();
    }
    opt.EnableDetailedErrors();
});
//builder.Services.AddScoped<FrameworkDbContext>();

报错内容:

System.InvalidOperationException: An attempt was made to use the model while it was being created. A DbContext instance cannot be used inside 'OnModelCreating' in any way that makes use of the model that is being created

minimal代码git地址

https://github.com/TerraMours/TerraMours_Gpt_Api/tree/MASAmininalAPI

MVC代码git地址

https://github.com/TerraMours/TerraMours_Gpt_Api

Reproduction Steps

minimal代码git地址

https://github.com/TerraMours/TerraMours_Gpt_Api/tree/MASAmininalAPI

MVC代码git地址

https://github.com/TerraMours/TerraMours_Gpt_Api

代码位置

目前问题出现的api:AnalysisMiniApiService 地址:https://github.com/TerraMours/TerraMours_Gpt_Api/blob/MASAmininalAPI/TerraMours/TerraMours/Domains/LoginDomain/MiniApi/AnalysisMiniApiService.cs 在这个service下的接口会同时调用。会出现上述问题。

Expected behavior

前端并发调用接口时,数据库查询正常

Actual behavior

前端并发调用接口查询数据库时,会出现报错:

System.InvalidOperationException: An attempt was made to use the model while it was being created. A DbContext instance cannot be used inside 'OnModelCreating' in any way that makes use of the model that is being created

Known Workarounds

No response

.NET version

net7.0

MASA Framework version

1.0.1-preview.10

Other information

包引用

<PackageReference Include="Masa.Contrib.Service.MinimalAPIs" Version="1.0.1-preview.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.5">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
 <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" />
Qinyouzeng commented 6 months ago

把 IAnalysisService analysisService由构造函数注入 改到下面的method上进行注入。

  1. 构造函数注入的服务对象类似单例模式,在服务注册时创建,并会一直存在,如果注入的对象有实现IDispose接口的话,长时间没有访问该路由下的接口,这些对象就会被dispose掉

  2. 方法上进行对象注入: `

    [Authorize]
    public async Task<IResult> TotalAnalysis([FromServices] IAnalysisService analysisService ,[FromBody] AnalysisBaseReq req)
    {
        var res = await analysisService .TotalAnalysis(req);
        return Results.Ok(res);
    }

`

注入模式默认类似AddScoped,每次调用该方法,都会执行相应的注入构造产生相应新的(跟对象服务的注入模式有关,如果为AddSingleton,则每次仍旧是同一个对象)实例。