Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
316 views
in Technique[技术] by (71.8m points)

entity framework - Databasecontext gets disposed - Custom (nested) service(s)

I try to inject my DbContext using services.AddDbContext in my Startup.cs. It's gets injected in the service that needs to handle every call to the DB. This AzureService gets injected in other services that actually need the data. When I try this however I always get a system.ObjectDiposedException on de DbContext inside AzureService.

When I inject it directly in the CompareService it just work, so I'm probably making a grave mistake with the nested services. Help/insights much appreciated.

code:

Startup.cs

        services.AddDbContext<SchoolDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("SchoolSyncDb")));
        services.AddScoped<IAzureService, AzureService>();
        services.AddScoped<ICompareService, CompareService>();

AzureService

public class AzureService : IAzureService
{
    private  SchoolDbContext schoolDbContext;
    private  IMapper mapper;
    private  IHelperService helperSrv;

    public AzureService(SchoolDbContext _sdb, IMapper _mapper, IHelperService _helper)
    {
        schoolDbContext = _sdb;
        mapper = _mapper;
        helperSrv = _helper;
    }

CompareService

public class CompareService: ICompareService
{
    private readonly IWisaService wisaSrv;
    private readonly ISmartschoolService smtSrv;
    private readonly IAzureService azureSrv;
    private readonly IHelperService helperSrv;
    private readonly ILoggerService loggerSrv;


    public CompareService(IWisaService _ws, ILoggerService _ls, ISmartschoolService _ss, IAzureService _as, IHelperService _hs)
    {
        wisaSrv = _ws;
        smtSrv = _ss;
        azureSrv = _as;
        helperSrv = _hs;
        loggerSrv = _ls;
    }

trying to get data from the AzureService in the CompareService fails because the DbContext in the AzureService is Diposed.

  List<AdbStudentModels> DbList;
        try
        {
            DbList = azureSrv.GetAllStudentInDbBySchool(school);
        }

In AzureService

 public List<AdbStudentModels> GetAllStudentInDbBySchool(string school)
    {
        try
        {
            return schoolDbContext.AdbStudentModels.Where(i => i.School.Schoolnaam.Equals(school)).ToList();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

It's seems that I've found a solution reading this article. I changed the lifecycle for CompareService to singleton and the one from AzureService to transient.

I still inject AzureService into CompareService but instead of injecting the DbContext into the azureService, I inject IServiceprovider as a whole and create a scope for the DbContext.

I am by no means a professional programmer, so I'm not claiming this to be the solution or the way to implement this correctly. It just does what I need at the moment.

Startup.cs

services.AddDbContext<SchoolDbContext>(options => options.UseSqlServer(connString));
        services.AddTransient<IAzureService, AzureService>();
        services.AddSingleton<ICompareService, CompareService>();

CompareService

    private readonly IAzureService azureSrv;

    public CompareService(IAzureService _as)
    {
        azureSrv = _as;
    }

AzureService

    private IServiceProvider sp;

    public AzureService(IServiceProvider _sp)
    {
        sp = _sp;
    }

Method in AzureService needing the DbContext (using scope)

public List<AdbStudentModels> GetAllStudentInDbBySchool(string school)
    {
        try
        {
            using (var scope = sp.CreateScope())
            {
                SchoolDbContext db = scope.ServiceProvider.GetRequiredService<SchoolDbContext>();

                return db.AdbStudentModels.Where(i => i.School.Schoolnaam.Equals(school)).ToList();
            }
            
        }
        catch (Exception ex)
        {
            throw new Exception("GetAllStudentInDbBySchool" + " / " + ex);
        }
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...