Pregunta

Tengo un servicio de Windows y quiero asegurarme de que mi EF ObjectContext se elimine cada vez que se ejecuta.El servicio dura más cada vez que se ejecuta.Parece que ObjectContext sigue creciendo.¿Mi ObjectContext debería registrarse de manera diferente o estoy haciendo algo mal?

Una visión general de lo que estoy haciendo.

  • Estoy usando Cuarzo.NET para programar mi servicio
  • Estoy usando Atlas para configurar y configurar mi servicio de Windows
  • Estoy usando autofac como mi COI
  • Estoy usando Entity Framework como mi modelo de datos.

Tutorial del código:

  • Entonces, el programa comienza registrando el servicio usando Atlas.
  • Atlas registrará mis registros de autofac que se encuentran en el módulo MyModule
  • MyModule registra el ObjectContext en InstancePerLifetimeScope (¿Es este el alcance correcto?), luego tendrá una instancia de mi UnitOfWork personalizado como InstancePerLifetimeScope (¿Es este el alcance correcto?).
  • MyService está alojado en Atlas, que inyecta un programador 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 consigue mis cosas.

Cuando se ejecuta el trabajo, llama y recibe mis cosas. Cada vez que se ejecuta, lleva más tiempo (ejemplo:2 minutos la primera vez que se ejecuta, 4 minutos la segunda vez que se ejecuta el servicio, 6 minutos la siguiente, 8 la siguiente y así sucesivamente).Parece que mi ObjectContext se hace cada vez más grande.Los datos que extrae no han cambiado, siguen siendo el mismo número de filas y columnas.Entonces creo que mis registros son incorrectos, ¿es este el caso?Si no, ¿puedes ver algún 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"; }
    }
}

Mi servicio

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>();
    }
}
¿Fue útil?

Solución

Lo está registrando correctamente, pero no lo está utilizando durante su vida útil, por lo que no se eliminará porque técnicamente su vida útil es la vida útil de la aplicación.

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

Crear un LifetimeScope en tus AutofacJobListener en Ejecución y disponer de él en Ejecutado.Esto forzará la vida útil de todas las instancias resueltas en ese alcance, es decir.su ObjectContext, para existir solo durante la duración de ese alcance, la ejecución del trabajo.

Agrega algo como

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

y

_lifetimeScope.Dispose();

en los métodos adecuados.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top