Am I correctly registering an ObjectContext with AutoFac?

I have a Windows service, and I want my EF ObjectContext to be deleted between each its launch. The service runs longer each time it runs. It appears ObjectContext is still growing. Should my ObjectContext be registered differently or am I doing something wrong?

Overview of what I am doing.

  • I am using Quartz.NET to plan my service.
  • I use Atlas to configure and configure the Windows service
  • I use Autofac as my IoC
  • I use Entity Framework as my data model

Walkthru Code:

  • So, the program begins by registering the service using Atlas.
  • Atlas will register the registration of autofiles that are hosted in the MyModule module
  • MyModule registers an ObjectContext in an instance of InstancePerLifetimeScope (is this the correct scope?), Then it will have an instance of my custom UnitOfWork as an instance of InstancePerLifetimeScope (is this the correct scope?).
  • MyService is hosted in Atlas, which receives the Quartz Scheduler and AutofacJobListener property, and runs a job (MyJob) every 5 minutes when the service starts.
  • MyJob, which receives an instance of the ObjectContext property entered into it from AutofacJobListener. This work accesses the database and gets my stuff.

When a job starts, it gets called and gets my stuff every time it runs, it takes longer (example: 2 minutes the first time it starts, 4 minutes the second time the service works, 6 minutes the next, 8 the next and soon ) It seems my ObjectContext is getting bigger and bigger every time. The data of its extrusion has not changed, still the same number of rows and columns. So I think my registrations are wrong, is that so? If you do not see a problem with what I am doing?

Program

static class Program { /// <summary> /// The main entry point for the application. /// </summary> static void Main(string[] args) { var configuration = Host.Configure<MyService>(c => { c.AllowMultipleInstances(); c.WithRegistrations(b => b.RegisterModule(new MyModule())); }, args); Host.Start(configuration); } } 

Module

 public class MyModule : Module { protected override void Load(ContainerBuilder builder) { LoadQuartz(builder); LoadServices(builder); LoadInfrastructure(builder); } private void LoadInfrastructure(ContainerBuilder builder) { builder.Register(c => new ObjectContext()) .As<IObjectContext>() .InstancePerLifetimeScope(); builder.Register(c => new UnitOfWork(c.Resolve<IObjectContext>())) .As<ISession>().As<IObjectContextProvider>() .InstancePerLifetimeScope(); } private void LoadQuartz(ContainerBuilder builder) { builder.Register(c => new StdSchedulerFactory().GetScheduler()).As<IScheduler>().InstancePerLifetimeScope(); builder.Register(c => new AutofacJobListener(c)).As<IJobListener>(); } private void LoadServices(ContainerBuilder builder) { builder.RegisterType<MyService>().As<IAmAHostedProcess>().PropertiesAutowired(); } } 

AutofacJobListener

 public class AutofacJobListener : IJobListener { private readonly IComponentContext _container; public AutofacJobListener(IComponentContext container) { _container = container; } public void JobToBeExecuted(JobExecutionContext context) { _container.InjectUnsetProperties(context.JobInstance); } public void JobExecutionVetoed(JobExecutionContext context) { /*noop*/ } public void JobWasExecuted(JobExecutionContext context, JobExecutionException jobException) { /*noop*/ } public string Name { get { return "AutofacInjectionJobListener"; } } } 

MyService

 public class MyService : IAmAHostedProcess { public IScheduler Scheduler { get; set; } public IJobListener AutofacJobListener { get; set; } #region Implementation of IAmAHostedProcess public void Start() { var trigger = TriggerUtils.MakeMinutelyTrigger(5); trigger.Name = @"Job Trigger"; Scheduler.ScheduleJob(new JobDetail("Job", null, typeof(MyJob)), trigger); Scheduler.AddGlobalJobListener(AutofacJobListener); Scheduler.Start(); } public void Stop() { Scheduler.Shutdown(); } public void Resume() { } public void Pause() { } #endregion } 

My job

 public class MyJob : IJob { public IObjectContext ObjectContext { get; set; } public void Execute(JobExecutionContext context) { var myStuff = ObjectContext.GetIQueryable<Stuff>(); } } 
+6
source share
1 answer

You register it correctly, but you do not use it within the validity period, therefore it cannot be disposed of, since technically your lifetimecope is the lifetime of the application.

Atlas registers everything and works in the lifetimecope of the application, so if you only allow instances without creating a lifetimecope, they are resolved for the scope of the application. In Windows applications, the lifetimecope is not predefined for you; as in web applications, you must define it. In your case, you need to create a lifetimecope surrounding the execution of one task.

Create a LifetimeScope in AutofacJobListener in Executing and delete it in Executed. This will result in the lifetime of all instances allowed in this scope, i.e. Your ObjectContext , will exist only throughout this area, the job.

Add something like

 _lifetimeScope = container.BeginLifetimeScope(); _lifetimeScope.InjectUnsetProperties(context.JobInstance); 

and

 _lifetimeScope.Dispose(); 

in appropriate methods.

+6
source

Source: https://habr.com/ru/post/890716/


All Articles