2011-06-16 100 views
6

我有一个Windows服务,我想确保我的EF ObjectContext在每次运行之间被处置。每次执行服务时都会运行更长时间。看起来ObjectContext不断增长。我的ObjectContext应该以不同的方式注册还是我做错了什么?我正确使用AutoFac注册ObjectContext吗?

我在做什么的概述。

  • 我使用Quartz.NET来安排我的服务
  • 我使用Atlas配置和安装我的窗口服务
  • 我用Autofac作为我的IoC
  • 我使用实体框架因为我的数据模型

Walkthru代码:

  • 因此,程序通过使用Atlas注册服务开始。
  • Atlas将注册在被安置在模块MyModule的我autofac注册
  • MyModule的寄存器中的ObjectContext在InstancePerLifetimeScope(这是正确的范围是什么?),那么就会有一次,我的自定义的UnitOfWork作为InstancePerLifetimeScope的情况下(这是该正确的范围?)。
  • MyService由Atlas托管,Atlas获取Quartz调度程序和AutofacJobListener属性,并在服务启动时安排作业(MyJob)每5分钟运行一次。
  • MyJob获取从AutofacJobListener注入到ObjectContext属性的实例。这项工作叫出数据库,让我得到我的东西。

作业运行时它的每一个运行时,它需要更长的时间调出并得到我的东西(例如:5分钟运行,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>(); 
    } 
} 

回答

6

您正确注册了,但你不使用它一辈子的范围之内,所以它不会被丢弃,因为技术上的lifetimescope是应用程序的生命。

阿特拉斯寄存器一切并运行应用程序的lifetimescope,所以如果你只解决的情况下,不创建lifetimescope,他们正在解决的应用程序的生命周期的范围。在Windows应用程序li​​fetimescope不是预先确定你,因为它是在Web应用程序,您必须定义它。在你的情况下,你需要创建一个围绕单个作业执行的生命周期。

在您的AutofacJobListener上创建一个LifetimeScope执行并将其处置为执行。这将迫使所有实例的生命周期在该范围解决,即你的ObjectContext,只为该范围的持续时间,作业的执行存在。

添加类似

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

_lifetimeScope.Dispose();
在适当的方法

+0

谢谢正是我一直在寻找,我居然进了一步,并使用阿特拉斯的力量。我改变了我的AutofacJobListener在Atlas.ContainerProvider.Instance则使用的ContainerProvider的BeginLifetimeScope通过() – Mark 2011-06-17 16:04:38