2011-06-16 19 views
6

Tengo un servicio de Windows y quiero asegurarme de que mi EF ObjectContext se elimina entre cada vez que se ejecuta. El servicio se ejecuta más tiempo cada vez que se ejecuta. Parece que ObjectContext sigue creciendo. ¿Mi ObjectContext debe registrarse de manera diferente o estoy haciendo algo mal?¿Estoy registrando el ObjectContext usando AutoFac correctamente?

Una visión general de lo que estoy haciendo.

  • Quartz.NET estoy usando para programar mi servicio
  • estoy usando Atlas para configurar y servicio de configuración de las ventanas de mi
  • estoy usando Autofac como mi COI
  • estoy usando Entity Framework como mi modelo de datos

guka del código:

  • Así que el programa comienza registrando el servicio usando Atlas.
  • Atlas registrará mis registros autofac que están alojados en MyModule módulo
  • MyModule registra el ObjectContext en InstancePerLifetimeScope (¿Es este el alcance correcto?), Entonces tendrá una instancia de mi costumbre UnitOfWork como InstancePerLifetimeScope (¿Es este el ¿alcance correcto?).
  • MyService está hospedado por Atlas, que inyecta un programador de Quartz y la propiedad AutofacJobListener y programa el trabajo (MyJob) para que se ejecute cada 5 minutos cuando se inicia el servicio.
  • MyJob que obtiene la instancia de la propiedad ObjectContext inyectada desde AutofacJobListener. Este trabajo llama a la base de datos y me da mis cosas.

Cuando la tarea se ejecuta, llama y obtiene mis cosas cada vez que se ejecuta, tarda más (ejemplo: 2 minutos la primera vez que se ejecuta, 4 minutos la segunda vez que se ejecuta el servicio, 6 minutos el siguiente, 8 el siguiente y así sucesivamente). Parece que mi ObjectContext es cada vez más grande. Los datos de su extracción no han cambiado, todavía el mismo número de filas y columnas. Entonces, creo que mis registros son incorrectos, ¿es este el caso? Si no, ¿puedes ver un problema con lo que estoy haciendo?

Programa

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); 
    } 
} 

Módulo

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 
} 

mi trabajo

public class MyJob : IJob 
{ 
    public IObjectContext ObjectContext { get; set; } 

    public void Execute(JobExecutionContext context) 
    { 
     var myStuff = ObjectContext.GetIQueryable<Stuff>(); 
    } 
} 

Respuesta

6

está registrando correctamente, pero que no lo esté utilizando dentro de un ámbito de por vida por lo que no será desechado porque técnicamente su lifetimescope es la vida de la aplicación.

Atlas registra todo y se ejecuta en el periodo de vida de la aplicación, por lo que si solo resuelve instancias, sin crear un ciclo de vida, se resuelven por el alcance de la vida útil de la aplicación. En aplicaciones de Windows, un tiempo de vida útil no está predeterminado para usted, ya que está en aplicaciones web, debe definirlo. En su caso, necesita crear un ciclo de vida que rodee la ejecución de un solo trabajo.

Cree LifetimeScope en su AutofacJobListener en el Ejecutar y deséchelo en Ejecutado. Esto forzará la vida de todas las instancias resueltas en ese ámbito, es decir, su ObjectContext, para que exista solo durante la duración de ese alcance, la ejecución del trabajo.

añadir algo como

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

y

_lifetimeScope.Dispose();

en los métodos apropiados.

+0

Gracias exactamente lo que estaba buscando y en realidad fui un paso más allá y usé el poder de Atlas. Cambié mi AutofacJobListener para pasarlo en Atlas.ContainerProvider.Instance y luego utilicé el BeginLifetimeScope de ContainerProvider() – Mark

Cuestiones relacionadas