6

私はWindowsサービスを使用しており、EFObjectContextが実行されるたびに確実に破棄されるようにしたいと考えています。サービスは、実行するたびに長く実行されます。ObjectContextは成長し続けているようです。ObjectContextを別の方法で登録する必要がありますか、それとも何か間違ったことをしていますか?

私がしていることの概要。

  • Quartz.NETを使用してサービスをスケジュールしています
  • Atlasを使用してWindowsサービスを構成およびセットアップしています
  • IoCとしてAutofacを使用しています
  • データモデルとしてEntityFrameworkを使用しています

コードのウォークスルー:

  • そのため、プログラムはAtlasを使用してサービスを登録することで開始されます。
  • Atlasは、モジュールMyModuleに格納されているautofac登録を登録します
  • MyModuleはObjectContextをInstancePerLifetimeScopeに登録し(これは正しいスコープですか?)、カスタムUnitOfWorkのインスタンスをInstancePerLifetimeScopeとして一度持つことになります(これは正しいスコープですか?)。
  • MyServiceはAtlasによってホストされ、QuartzスケジューラーとAutofacJobListenerプロパティが注入され、サービスの開始時に5分ごとに実行されるようにジョブ(MyJob)がスケジュールされます。
  • AutofacJobListenerからObjectContextプロパティのインスタンスが注入されたMyJob。この仕事はデータベースを呼び出して、私に私のものを手に入れます。

ジョブが実行されると、実行するたびに呼び出して私のものを取得するのに時間がかかります(例:最初の実行で2分、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>();
    }
}
4

1 に答える 1

6

正しく登録していますが、ライフタイムスコープ内で使用していないため、技術的にはライフタイムスコープがアプリケーションの存続期間であるため、破棄されません。

Atlasはすべてを登録し、アプリケーションのライフタイムスコープで実行されるため、ライフタイムスコープを作成せずにインスタンスのみを解決すると、アプリケーションのライフタイムスコープで解決されます。Windowsアプリケーションでは、ライフタイムスコープはWebアプリケーションの場合のように事前に決定されていないため、定義する必要があります。あなたの場合、単一のジョブの実行を取り巻くライフタイムスコープを作成する必要があります。

実行時にを作成し、実行時に破棄しますLifetimeScopeAutofacJobListenerこれにより、そのスコープで解決されたすべてのインスタンスの存続期間、つまり、ObjectContextが、そのスコープの期間、つまりジョブの実行中にのみ存在するようになります。

次のようなものを追加します

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

_lifetimeScope.Dispose();

適切な方法で。

于 2011-06-17T00:24:19.697 に答える