Правильно ли я регистрирую ObjectContext, используя AutoFac? - PullRequest
6 голосов
/ 17 июня 2011

У меня есть служба Windows, и я хочу убедиться, что мой EF ObjectContext утилизируется между каждым его запуском.Служба работает дольше каждый раз, когда она выполняется.Кажется, что ObjectContext продолжает расти.Должен ли мой ObjectContext быть зарегистрирован по-другому или я что-то не так делаю?

Обзор того, что я делаю.

  • Я использую Quartz.NET чтобы запланировать мой сервис
  • Я использую Атлас для настройки и настройки моей службы Windows
  • Я использую Autofac в качестве IoC
  • Я использую Entity Framework в качестве модели данных

Краткое описание кода:

  • Итак, программа запускает регистрацию службы с помощью Atlas.
  • Atlas зарегистрирует мои автоматические регистрации, которые размещены в модуле MyModule
  • MyModule регистрирует ObjectContext в InstancePerLifetimeScope (это правильная область?), Тогда у него будет один раз мой пользовательский UnitOfWork какInstancePerLifetimeScope (Это правильная область?).
  • MyService размещается Atlas, который получает планировщик Quartz и свойство AutofacJobListener и планирует задание (MyJob) запускаться каждые 5 минут, когдаслужба запускается.
  • MyJob, который получает экземпляр свойства ObjectContext, внедренный в него из AutofacJobListener.Эта работа обращается к базе данных и получает мои вещи.

Когда задание запускается, оно вызывает и получает мои данные при каждом запуске, это занимает больше времени (например: 2 минуты при первом запуске, 4 минуты при втором запуске службы, 6 минутследующий, 8 следующий и так далее).Кажется, мой ObjectContext с каждым разом становится все больше и больше.Данные, которые он извлекает, не изменились, все равно количество строк и столбцовТак что я думаю, что мои регистрации неверны, так ли это?Если нет, вы можете увидеть проблему с тем, что я делаю?

Программа

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

Модуль

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
}

Моя работа

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

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

1 Ответ

6 голосов
/ 17 июня 2011

Вы регистрируете его правильно, но не используете его в пределах срока действия, поэтому он не будет утилизирован, потому что технически ваш жизненный цикл - это жизнь приложения.

Atlas регистрирует все и работает ввремя жизни приложения, поэтому, если вы разрешаете только экземпляры, не создавая время жизни, они разрешаются для объема времени жизни приложения.В приложениях для Windows время жизни не определено для вас, как в веб-приложениях, вы должны определить его.В вашем случае вам необходимо создать жизненный цикл, связанный с выполнением одного задания.

Создайте LifetimeScope в вашем AutofacJobListener при выполнении и уничтожьте его при выполнении.Это заставит время существования всех экземпляров, разрешенных в этой области, то есть вашего ObjectContext, существовать только на время этой области, до выполнения задания.

Добавьте что-то вроде

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

и

_lifetimeScope.Dispose();

в соответствующих методах.

...