簡體   English   中英

Autofac-DataContext未在生命周期范圍的末尾處置

[英]Autofac - DataContext not being disposed at end of lifetime scope

我有一個命令行程序,它將數據導入到我的系統中。 因為它將數據插入許多表中,所以我需要進行更改跟蹤。 為了嘗試防止作業隨時間推移而變慢,我使用了Autofac(我的依賴項注入框架)來創建一個內部生命周期范圍,從中可以解析依賴項。 在每個批處理的末尾,我將重新創建生存期范圍並獲取依賴項的新實例。 問題是,當我這樣做時,UnitOfWork依賴的DataContext不會每次都刷新,從而導致作業變慢,並最終在完成之前終止。

我可以在調試時通過在DbContext上設置“ Make Object ID”來查看此信息,例如

在此處輸入圖片說明

每批處理后,對象ID仍為$ 2,表明DataContext實例未獲取新實例。 為什么沒有獲得新實例?

我的代碼如下所示:

foreach (var batch in data.Batch(10))
{
    using (var scope = LifetimeScope.BeginLifetimeScope(b =>
    {
        b.RegisterType<UnitOfWork>.AsImplementedInterfaces().PropertiesAutowired().InstancePerLifetimeScope();
        b.RegisterType<MyService1>.AsImplementedInterfaces().PropertiesAutowired().InstancePerLifetimeScope();
        b.RegisterType<MyService2>.AsImplementedInterfaces().PropertiesAutowired().InstancePerLifetimeScope();
        b.RegisterGeneric(typeof(EntityBaseRepository<>)).As(typeof(IEntityBaseRepository<>)).InstancePerLifetimeScope();
    }))
    {
        UnitOfWork = scope.Resolve<IUnitOfWork>();
        MyService1 = scope.Resolve<IMyService1>();
        MyService2 = scope.Resolve<IMyService2>();
        Thing1Repository = scope.Resolve<IEntityBaseRepository<Thing1Repository>>();
        Thing2Repository = scope.Resolve<IEntityBaseRepository<Thing2Repository>>();

        foreach (var row in batch)
        {
            try
            {
                ParseRow(row);
            }
            catch (Exception e)
            {
                JobLogger.Error(e, "Failed to parse row. Exception: " + e.Message);
                throw;
            }

        }
    }
}

據我了解,當我獲得依賴項的新實例時,子依賴項也將獲得新的實例嗎? 為什么原始DataContext仍然懸而未決?

我的UnitOfWork看起來像這樣:

public class UnitOfWork : Disposable, IUnitOfWork
{
    private readonly IDbFactory _dbFactory;
    private DataContext _dbContext;

    public UnitOfWork(IDbFactory dbFactory)
    {
        _dbFactory = dbFactory;
    }

    public DataContext DbContext => _dbContext ?? (_dbContext = _dbFactory.Initialise());

    public void Commit()
    {
        DbContext.Commit();
    }
}

我的DbFactory負責創建DataContext的新實例:

public class DbFactory : Disposable, IDbFactory
{
    DataContext _dbContext;

    public DbFactory()
    {
        _dbContext = new DataContext();
    }

    public DataContext Initialise()
    {
        return _dbContext ?? (_dbContext = new DataContext());
    }

    protected override void DisposeCore()
    {
        _dbContext?.Dispose();
    }
}

當程序首次啟動時,通過調用以下方法來掃描程序集來注冊我的服務:

AutofacConfig.InitialiseJobRunner();

在此方法中,我注冊這樣的類型:

builder.RegisterType<DataContext>().AsSelf().InstancePerMatchingLifetimeScope(lifetimeScope);
builder.RegisterGenericInstance(typeof(EntityBaseRepository<>), typeof(IEntityBaseRepository<>), lifetimeScope);
builder.RegisterAssemblyInterfaces(Assembly.Load(Data), lifetimeScope);

RegisterAssemblyInterfaces實現為:

public static IRegistrationBuilder<object, ScanningActivatorData, DynamicRegistrationStyle>
        RegisterAssemblyInterfaces(this ContainerBuilder builder, Assembly assembly, object lifetimeScope)
{
    return builder.RegisterAssemblyTypes(assembly)
        .AsImplementedInterfaces()
        .InstancePerMatchingLifetimeScope(lifetimeScope);
}

當您注冊程序集接口時,如下所示

public static IRegistrationBuilder<object, ScanningActivatorData, DynamicRegistrationStyle>
    RegisterAssemblyInterfaces(this ContainerBuilder builder, Assembly assembly, object lifetimeScope)
{
    return builder.RegisterAssemblyTypes(assembly)
        .AsImplementedInterfaces()
        .InstancePerMatchingLifetimeScope(lifetimeScope);
}

我的猜測是您的DbFactory也以這種方式注冊。 在這種情況下(根據: https : //autofac.readthedocs.io/en/latest/lifetime/instance-scope.html#instance-per-matching-lifetime-scope ),您將獲得與工廠相同的工廠實例。子作用域未命名。 嘗試添加

b.RegisterType<DbFactory>.AsImplementedInterfaces().PropertiesAutowired().InstancePerLifetimeScope();

在循環中,或將DbFactory更改為始終在Initialize方法中返回新的上下文,而不是如果已實例化則返回相同的上下文。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM