我是否正确使用AutoFac注册ObjectContext?

Mar*_*ark 6 .net autofac atlas quartz.net entity-framework-4

我有一个Windows服务,我想确保我的EF ObjectContext在每次运行之间被处理掉.每次执行时,服务运行的时间都会更长.似乎ObjectContext不断增长.我的ObjectContext应该注册不同还是我做错了什么?

我正在做什么的概述.

  • 我正在使用Quartz.NET来安排我的服务
  • 我正在使用Atlas来配置和设置我的Windows服务
  • 我正在使用Autofac作为我的IoC
  • 我正在使用Entity Framework作为我的数据模型

Walkthru的代码:

  • 因此,该计划通过使用Atlas注册服务开始.
  • Atlas将注册我的autofac注册,这些注册位于模块MyModule中
  • MyModule在InstancePerLifetimeScope中注册ObjectContext(这是正确的范围?),然后它将我的自定义UnitOfWork的一个实例作为InstancePerLifetimeScope(这是正确的范围?).
  • MyService由Atlas托管,它获取Quartz调度程序和AutofacJobListener属性,并在服务启动时调度作业(MyJob)每5分钟运行一次.
  • MyJob从AutofacJobListener中获取ObjectContext属性的实例.这个工作呼唤数据库,让我得到我的东西.

当作业运行时,它会在每次运行时调出并获取我的东西需要更长的时间(例如:第一次运行时为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);
    }
}
Run Code Online (Sandbox Code Playgroud)

模

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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"; }
    }
}
Run Code Online (Sandbox Code Playgroud)

为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
}
Run Code Online (Sandbox Code Playgroud)

我的工作

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

    public void Execute(JobExecutionContext context)
    {
        var myStuff = ObjectContext.GetIQueryable<Stuff>();
    }
}
Run Code Online (Sandbox Code Playgroud)

Ada*_*dam 6

您正在正确注册,但是您没有在生命周期范围内使用它,因此它不会被处理掉,因为从技术上讲,您的生命周期镜是应用程序的生命周期.

Atlas注册所有内容并在应用程序的lifetimescope中运行,因此如果您只解析实例而不创建生命周期镜,则可以解决它们在应用程序生命周期范围内的问题.在Windows应用程序中,生命周期镜不像您在Web应用程序中那样预先确定,您必须对其进行定义.在您的情况下,您需要创建一个围绕单个作业执行的生命周期.

创建一个LifetimeScope在您AutofacJobListener的执行和上执行处置.这将强制在该范围内解析的所有实例(即您的)的生命周期ObjectContext仅在该范围的持续时间内存在,即作业的执行.

添加类似的东西

_lifetimeScope = container.BeginLifetimeScope();
_lifetimeScope.InjectUnsetProperties(context.JobInstance);
Run Code Online (Sandbox Code Playgroud)

和

_lifetimeScope.Dispose();
Run Code Online (Sandbox Code Playgroud)

在适当的方法.