[英]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.