簡體   English   中英

Azure WebJobs-單個WebJob和Ef錯誤中的多個后台任務嘗試在配置上下文時使用上下文

[英]Azure WebJobs - multiple background task in single WebJob and Ef error An attempt was made to use the context while it is being configured

我有多個要運行的后台批處理作業,並且被要求有一個webJob來運行所有任務,而我需要安排這些任務在不同時間運行。

我使用了webJob.Extensions中的Timer功能。

即在Program.cs中

var config = new JobHostConfiguration
            {
                JobActivator = new AutofacActivator(ContainerConfig<Functions>.GetContainer())
            };

            if (config.IsDevelopment)
            {
                config.UseDevelopmentSettings();
            }
            config.UseTimers();

            var host = new JobHost(config);
            host.RunAndBlock();

並且該函數將具有多種方法,並在30分鍾的間隔內觸發。

public void ProcessMethod1([TimerTrigger("0 0/30 * * * *")] TimerInfo timer)
{
   //Logic
}

public void ProcessMethod2([TimerTrigger("0 0/30  * * * *")] TimerInfo timer)
{
   //Logic
}

問題:由於我正在使用Autofac DI。 我在作業開始時為dbContext創建實例

JobActivator = new AutofacActivator(ContainerConfig<Functions>.GetContainer())

在執行webJob時,執行DB選擇時出現錯誤,例如“試圖在配置上下文時使用上下文”。

由於我將范圍指定為InstancePerLifetimeScope()。 我想知道Two操作是否將獲得相同的實例?

同樣對於日志記錄,我也有類似的問題,因為看起來這兩個不同的操作僅創建了一個實例。

我想要的是根據操作為DBCOntext和Logger擁有一個單獨的實例。 請告訴我如何為這種情況設置DI。

更新:

public class AutofacActivator: IJobActivator
    {
        private readonly Autofac.IContainer _container;

        public AutofacActivator(Autofac.IContainer container)
        {
            _container = container;
        }

        public T CreateInstance<T>()
        {
            return _container.Resolve<T>();
        }
    }

 internal class WebJobIocModule<T> : Autofac.Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            if (builder == null)
                throw new ArgumentNullException("WebJobBuilder");


            //Cascade  
            builder.RegisterModule(new BusinessObjectIocModule());

            // Register the functions class - WebJobs will discover our triggers this way
            builder.RegisterType<T>();
        }
    }



  public class BusinessObjectIocModule :Autofac.Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            if(builder == null) throw new ArgumentNullException("BusinessObjectBuilder");


            //Cascade
            builder.RegisterModule(new DataAccessRepoIocModule());

            builder.RegisterType<BusinessObjBpc>().AsImplementedInterfaces();

        }
    }

在DataAccessIOC中:

 string connectionString = ConfigurationManager.ConnectionStrings["DBConnectionAppKeyName"].ConnectionString;
            optionsStagingBuilder.UseSqlServer(connectionString);

            builder.RegisterType<DataAccessDbContext>()
                .AsSelf()
                .WithParameter("options", optionsStagingBuilder.Options)
                .InstancePerLifetimeScope();

如果對DbContext使用LifetimeScope ,則應確保使用以下代碼在每次執行處理方法時都創建一個新的作用域:

public void ProcessMethod1([TimerTrigger("0 0/30 * * * *")] TimerInfo timer)
{
    using (var scope = container.BeginLifetimeScope())
    {
        //Logic
    }
}

可以,但是我認為它可能會有副作用。 同樣,對於其他組件,在處理方法的每次執行中不實例化它們也更為有效。 也許您想使用其他范圍。

更新 -如何將容器注入函數構造函數中:

在構造函數中,可以使用參數Func<IContainer>代替IContainer 它將作為一個集裝箱工廠。

在構建容器時(在工作開始時,在構建容器時),您將注冊容器工廠的實例:

Func<IContainer> containerFactory = () => yourContainer;
...
builder.RegisterInstance(containerFactory);

然后在構造函數中,讓Autofac注入工廠並將容器存儲在屬性中:

public SomeConstructor(Func<IContainer> containerFactory, ...<other injected params>)
{
    ...
    this.container = containerFactory();
}

暫無
暫無

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

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