12

Time once again to appeal to greater minds.

I'm experiencing a very strange phenomenon. As the title states, I'm getting a NullReferenceException when trying to create an EF ObjectContext, but I only get the exception if I create the context within a Using statement. I've tried a variety of different ways, but it always ends up the same. And, of course, this is code that worked fine up until yesterday. It could possibly be relevant that my Windows Update ran yesterday morning.

Anyway...

If I try this

using (var context = new Entities(Env.Instance.Connection))
{
    //do a bunch of EF stuff
}

I get the NullReferenceException when creating my ObjectContext. Here Env.Instance.Connection is an EntityConnection that was created earlier in the program. I've stepped through to make sure the instance and EntityConnection both exist.

If I do it this way

var context = new Entities(Env.Instance.Connection);
//do a bunch of EF stuff
context.Dispose();

Everything works fine.

I've tried

using (var context = new Entities(Env.Instance.ConnectionName)) //the name of a connection string in my App.Config
{
    //do a bunch of EF stuff
}

I've tried

using (var context = new Entities(Env.Instance.ConnectionString)) //the actual connection string
{
    //do a bunch of EF stuff
}

I've even tried

using (var context = new Entities("metadata=res://*/MyDB.csdl|res://*/MyDB.ssdl|res://*/MyDB.msl;provider=System.Data.SqlClient;provider connection string=\"data source=MY-DB;initial catalog=MY-DB-PROD;persist security info=True;user id=dbuser;password=dbpass;multipleactiveresultsets=True;App=EntityFramework\""))
{
    //do a bunch of EF stuff
}

Doesn't matter. If I create the context within a using statement I always get a NullReferenceException.

I can step into the code of my data layer and I exit the ObjectContext constructor

public Entities(string connectionString) : base(connectionString, "Entities")
{
    this.ContextOptions.LazyLoadingEnabled = true;
    OnContextCreated();
}

But, as soon as I exit the constructor, the error is thrown.

Thoughts?

EDIT

In the absolute simplest iteration, the stack trace looks like so

at IkaPlus.ViewModel.MainVM.ProcessMail3(Object sender, DoWorkEventArgs e) in C:\SVN\IkaPlus\IkaPlus\ViewModel\MainVM.cs:Line 1371.
at IkaPlus.ViewModel.MainVM.RefillQueues() in C:\SVN\IkaPlus\IkaPlus\ViewModel\MainVM.cs:Line 832.

Ideally, ProcessMail3 would be called from a BackgroundWorker, thus its signature, but at the moment, I'm calling it from the main thread with null parameters.

To clarify, the ProcessMail3 method is intended to be called from a background worker, that's why it has sender and DoWorkEventArgs in its signature. But at the moment, I'm calling it directly from the main thread like so: ProcessMail3(null, null)

I think rism is on to something. If I do this

private void RefillQueues()
{
    using (var context = new Entities("metadata=res://*/MyDB.csdl|res://*/MyDB.ssdl|res://*/MyDB.msl;provider=System.Data.SqlClient;provider connection string=\"data source=MY-DB;initial catalog=MY-DB-PROD;persist security info=True;user id=dbuser;password=dbpass;multipleactiveresultsets=True;App=EntityFramework\""))
    {
    }

    ProcessMail3(null, null);
}

private void ProcessMail3(object sender, DoWorkEventArgs e)
{
    using (var context = new Entities("metadata=res://*/MyDB.csdl|res://*/MyDB.ssdl|res://*/MyDB.msl;provider=System.Data.SqlClient;provider connection string=\"data source=MY-DB;initial catalog=MY-DB-PROD;persist security info=True;user id=dbuser;password=dbpass;multipleactiveresultsets=True;App=EntityFramework\""))
    {
    }
}

The using statement in RefillQueues works, but the using statement in ProcessMail3 does not.

EDIT 2

To simplify it further, I've eliminated the parameters in the signature of the offending method. So, now I'm calling

private void RefillQueues()
{
    using (var context = new Entities("metadata=res://*/MyDB.csdl|res://*/MyDB.ssdl|res://*/MyDB.msl;provider=System.Data.SqlClient;provider connection string=\"data source=MY-DB;initial catalog=MY-DB-PROD;persist security info=True;user id=dbuser;password=dbpass;multipleactiveresultsets=True;App=EntityFramework\""))
    {
    }

    ProcessMail3();
}

private void ProcessMail3()
{
    using (var context = new Entities("metadata=res://*/MyDB.csdl|res://*/MyDB.ssdl|res://*/MyDB.msl;provider=System.Data.SqlClient;provider connection string=\"data source=MY-DB;initial catalog=MY-DB-PROD;persist security info=True;user id=dbuser;password=dbpass;multipleactiveresultsets=True;App=EntityFramework\""))
    {
    }
}

Same results. Using statement in the first method works. Using statement in the second method throws a NullReferenceException. There are no BackgroundWorkers running.

EDIT 3

So, I seem to have found what's causing my error, though I still can't explain it.

So, my ProcessMail3 method, actually looks like this (I've renamed it to EatCookies because...I like to eat cookies.)

private void EatCookies()
{
    #region Empty the Queue

    string s = "Queue 3";

    CicConnector.CreateInstance(SettingsHandler.Instance.CIC_PASSWORD,
              "MYSERVER",
              "C:\\temp");

    //Do a bunch of stuff

    #endregion

    #region EF Stuff

    using (var context = new Entities("metadata=res://*/MyDB.csdl|res://*/MyDB.ssdl|res://*/MyDB.msl;provider=System.Data.SqlClient;provider connection string=\"data source=MY-DB;initial catalog=MY-DB-PROD;persist security info=True;user id=dbuser;password=dbpass;multipleactiveresultsets=True;App=EntityFramework\""))
    {
    }

    #endregion
}

I haven't bothered to include the other lines of code because I've been stepping over them when I enter the method. Voodoo teching, I've found that if I comment out the line which creates my CiCConnector (shouldn't be relevant) my using statement after it works fine. If the line ISN'T commented out, regardless of whether I actually reach that line of code or not, the using statement doesn't work. If I set a breakpoint on the line where I create my string, and skip over the next line, going directly to my using statement, I get the NullReferenceException. If I comment out the CiCConnector line and do the same thing, the using statement works. And, again, if instead of a using statement, I simply create my ObjectContext then dispose of it manually later, it all works fine regardless of the CiCConnector line. This is all very strange.

EDIT 4

Oddly enough, the CiCConnector line does not cause the odd behavior if it's placed in the first method. So if I do

private void RefillQueues()
{
    string s = "Queue 3";

    CicConnector.CreateInstance(SettingsHandler.Instance.CIC_PASSWORD,
              "MYSERVER",
              "C:\\temp");

    using (var context = new Entities("metadata=res://*/MyDB.csdl|res://*/MyDB.ssdl|res://*/MyDB.msl;provider=System.Data.SqlClient;provider connection string=\"data source=MY-DB;initial catalog=MY-DB-PROD;persist security info=True;user id=dbuser;password=dbpass;multipleactiveresultsets=True;App=EntityFramework\""))
    {
    }

    EatCookies();
}

private void EatCookies()
{
    string s = "Queue 3";

    CicConnector.CreateInstance(SettingsHandler.Instance.CIC_PASSWORD,
              "MYSERVER",
              "C:\\temp");

    using (var context = new Entities("metadata=res://*/MyDB.csdl|res://*/MyDB.ssdl|res://*/MyDB.msl;provider=System.Data.SqlClient;provider connection string=\"data source=MY-DB;initial catalog=MY-DB-PROD;persist security info=True;user id=dbuser;password=dbpass;multipleactiveresultsets=True;App=EntityFramework\""))
    {
    }
}

The using statement in the first method works fine, but in the second method it breaks.

shrug Your guess is as good as mine. Probably better. I think I'll just chalk it up as an oddity and simply not use the using statement. But, if anyone has any insight, I'd be thrilled to find out what the heck is going on here.

Troy Frazier
  • 391
  • 3
  • 13
  • 2
    What is the call stack? – Justin Harvey Nov 12 '15 at 09:21
  • As per @JustinHarvey, a simple try catch block with a break point in the catch should suffice to work out the problem. – rism Nov 12 '15 at 09:25
  • Try cleaning the solution, close visual studio and open it again and rebuild, see if this helps :) – User2012384 Nov 12 '15 at 09:27
  • @JustinHarvey I've updated the question with the stack trace. rism It's in a try-catch block already User2012384 I've tried that. I've cleaned the solution, restarted VS, even restarted my computer. No luck. – Troy Frazier Nov 12 '15 at 09:32
  • The stack trace isn't showing any null ref exception, are you sure thats all of it? – Justin Harvey Nov 12 '15 at 09:39
  • @JustinHarvey StackTraces don't show exception type. Just stack frames. i.e. location. – rism Nov 12 '15 at 09:42
  • @TroyFrazier With your edit you've gone from "I cant create an objectcontext" to a bunch of other stuff possibly involving threading issues depending on the rest of your code. You need to narrow down the problem space. What your stacktrace does show is that the error doesn't appear to be in the constructor of your `Entities` class or else it would have something like `Entities..ctor`. Run just this `using (var context = new Entities(Env.Instance.ConnectionString)) { // do nothing }` from a clean/regular method. If it runs fine, it's not the using block but the method you're in. – rism Nov 12 '15 at 09:48
  • I think we don't know what is null here. You say "I can step into the code of my data layer and I exit the ObjectContext constructor" -> so context is not null.. maybe seeing other parts of the source code would help. Btw. a using is compiled into a try{}finally{context.Dispose()} block. – gregkalapos Nov 12 '15 at 09:49
  • The above also assumes `innerException` is null.... otherwise, of course, look in there first. – rism Nov 12 '15 at 09:50
  • @rism I don't believe it's a threading issue. As I said, the ProcessMail3 method is _intended_ to be called from a background worker, that's why it has sender and DoWorkEventArgs in its signature. But at the moment, I'm calling it directly from the main thread like so: ProcessMail3(null, null) – Troy Frazier Nov 12 '15 at 09:56
  • The mere fact that you're passing in nulls to a method intended to be called from a background thread and getting a `NullReferenceException` should be a pretty strong clue. As i say above, just rule it out by a quick refactor or otherwise unit test. – rism Nov 12 '15 at 10:04
  • Yes, the inner exception is null @rism I'm passing in nulls because the method signature asks for two parameters. I've tried changing the method to private void ProcessMail3() and calling it without any parameters and I get the same results. – Troy Frazier Nov 12 '15 at 10:09
  • If you change the signature to `private void ProcessMail2()`, does it work? Or `private void Processxyz()` – rism Nov 12 '15 at 10:13
  • Any chance that `OnContextCreated` interferes somewhere? – Gert Arnold Nov 18 '15 at 10:49

1 Answers1

1

EF manages the disposale for you so it is a little redundent to be using a using or explicitly disposing of it yourself

http://blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext.html

Snippit from the article

Before I talked with the devs on the EF team my answer was always a resounding “of course!”. But it’s not true with DbContext. You don’t need to be religious about calling Dispose on your DbContext objects. Even though it does implement IDisposable, it only implements it so you can call Dispose as a safeguard in some special cases. By default DbContext automatically manages the connection for you. Read to the end to hear the full story and see what the EF devs had to say about it.

Steven Ackley
  • 593
  • 7
  • 31