1

I have a large n-layered web project with self-tracking entities. I am using Entity Framework 5 and store the object context in HttpContext.Current.Items and dispose it on Application_EndRequest, as described here. I have a separate Class Library Project for the framework (CMS.Framework) which contains all the (self-tracking) POCO classes and much more logic. The actual ASP.NET Web Forms Applications refer to my CMS.Framework project. So far, it all works fine.

Now, I want to create a console application (for a scheduled server task) and also use my CMS.Framework class library. However, when a self-tracking entity tries to initalize (and calls the static CoreContext property), a System.NullReferenceException is thrown, as HttpContext.Current is null. This makes sense to me, as we are in a console app right now. Here is my code that breaks only in the console app:

    /// <summary>
    /// Gets the CmsCoreContext in order to access the CMS_Core DB. This context
    /// will be disposed when the application onloads (EndRequest).
    /// </summary>
    protected static CmsCoreContext CoreContext
    {
        get
        {
            if (!HttpContext.Current.Items.Contains("CoreContext"))
            {
                // Set Entity Framework context here and reuse it throughout the application
                HttpContext.Current.Items.Add("CoreContext", new CmsCoreContext());
            }
            return HttpContext.Current.Items["CoreContext"] as CmsCoreContext;
        }
    }

Where shall I store the new CmsCoreContext() when HttpContext.Current is null? Is there any console application context I can use? Any tips on this?

Community
  • 1
  • 1
Philippe
  • 43
  • 10
  • How long do you want to the context to live? Is running the console app from beginning to end the equivalent of a single http request? – Jace Rhea Jun 03 '13 at 17:55
  • Well, it kind of is. I am importing products and other info from an xml file. As the scheduled task is executed every few minutes, I guess handling all the import in one context is fine. – Philippe Jun 03 '13 at 18:05

1 Answers1

2

Presumably you only want a single instance of your object context for the entire lifetime of your console application? Something like this should work:

private static CmsCoreContext _coreContext;

protected static CmsCoreContext CoreContext
{
   get
   {
      if (!System.Web.Hosting.HostingEnvironment.IsHosted)
      {
         return _coreContext ?? (_coreContext = new CmsCoreContext());
      }

      var context = HttpContext.Current;
      if (context == null) throw new InvalidOperationException();

      if (!context.Items.Contains("CoreContext"))
      {
         context.Items.Add("CoreContext", new CmsCoreContext());
      }

      return (CmsCoreContext)context.Items["CoreContext"];
   }
}

// The Application_EndRequest event won't fire in a console application.
public static void ConsoleCleanup()
{
   if (_coreContext != null)
   {
      _coreContext.Dispose();
   }
}
Richard Deeming
  • 29,830
  • 10
  • 79
  • 151
  • Great, thanks for the answer. I wasn't aware that a static variable fixes my problem. – Philippe Jun 03 '13 at 18:03
  • Now I just came up with another thought: Do I have to dispose the static `_coreContext`? And yes, how? Or is it not mandatory? (Which would make my life easier, I guess.) – Philippe Jun 03 '13 at 18:40
  • I just checked - the way you described above @RichardDeeming doesn't dispose the `_coreContext`. What is the most elegant way to release the ressources? – Philippe Jun 03 '13 at 19:08
  • @Philippe: The `Application_EndEvent` obviously won't fire in a console application. You'll need to expose a static method to dispose the `_coreContext` instance which you can call when your application has finished. – Richard Deeming Jun 03 '13 at 19:39
  • Alright, I thought I have to go this way. Thank you very much for your help! – Philippe Jun 03 '13 at 20:25