Make a class library that has your Entity Framework model and object context. Then add a new console application to the solution. From the console app, reference the project that has your model.
Now type this in the console app:
static void Main(string[] args)
{
using (var context = new ExperimentalDbContext())
{
}
Console.ReadKey();
}
When you build, you'll get an error that reports:
The type 'System.Data.Entity.DbContext' is defined in an assembly that is not referenced. You must add a reference to assembly EntityFramework...yada yada yada...
Now, I have done this many times over the last few years, but every time I get this error, I once again helplessly search the Internet for the solution that I have forgotten by then.
The fix for this requires you to install the EntityFramework NuGet package in the ConsoleClient project.
So, my question is not about what the fix is, but rather why? Because it doesn't make any sense!
Just for the sake of completeness, I am using v6.1.3 of Entity Framework. But I have seen this error a number of times over the years with earlier versions as well.
Update
It appears that the problem is only when you use the using
code block that is meant to call Dispose
on IDisposable
s.
To test the hypothesis, create a console application, which references ClassLibrary1 in the same solution, which references ClassLibrary2 in the same solution, with the following code:
using ClassLibrary1;
using System;
namespace TestHypothesis1
{
class Program
{
// Testing the hypothesis presented in this answer: http://stackoverflow.com/a/38130945/303685
// This seems to be the behavior with just (or may be even others I haven't tested for)
// IDisposable.
// anotherFoo instance is created just fine, but the moment I uncomment
// the using statement code, it shrieks.
static void Main(string[] args)
{
//using (var foo = new Foo())
//{
// foo.Gar = "Gar";
// Console.WriteLine(foo.Gar);
//}
var anotherFoo = new Foo() { Gar = "Another gar" };
Console.WriteLine(anotherFoo.Gar);
Console.ReadKey();
}
}
}
using ClassLibrary2;
using System;
namespace ClassLibrary1
{
public class Foo: Bar, IDisposable
{
public string Gar { get; set; }
public void Dispose()
{
throw new NotImplementedException();
}
}
}
namespace ClassLibrary2
{
public class Bar
{
public string Name { get; set; }
}
}
And you will observe that the compiler complains about the missing reference only for the instantiation of the first Foo
and not for the second instance.
Strangely though, in the first EntityFramework example, if you removed the reference to EntityFramework.dll from the console application and changed the code in the Main
to this, it still complains about the missing reference.
static void Main(string[] args)
{
var context = new ExperimentalDbContext();
Console.ReadKey();
context.Dispose();
}
Additionally, if you comment out the call to context.Dispose()
, the last line of the code snippet above, the code still works fine even though it throws an InvalidOperationException
but that, I surmise, is due to a race condition of the context being disposed before its iterator completes its MoveNext
call.
static void Main(string[] args)
{
var context = new ExperimentalDbContext();
Console.ReadKey();
// context.Dispose();
}
So, the new additional question now becomes:
What is it about the way the using
statement is implemented that makes the compiler stop in its tracks in linking references?
The original question also remains.
Yet another update
It now appears that the problem may be zeroed down further to the call to the IDisposable.Dispose
method and the problem is therefore not with the implementation of the using
statement. The using
statement just seems to be an innocent assurance that Dispose
will be called and nothing else.
Therefore, in the above Foo
example, if you insert a call to anotherFoo.Dispose
at the end, the compiler starts to complain again. Like so:
using ClassLibrary1;
using System;
namespace TestHypothesis1
{
class Program
{
// Testing the hypothesis presented in this answer: http://stackoverflow.com/a/38130945/303685
// This seems to be the behavior with just (or may be even others I haven't tested for)
// IDisposable.
// anotherFoo instance is created just fine, but the moment I uncomment
// the using statement code, it shrieks.
// Final update:
// The trigger for the error seems to be the call to the Dispose method and not
// particularly the implementation of the using statement, which apparently, simply
// ensures that Dispose is called, as is also well-known and documented.
static void Main(string[] args)
{
//using (var foo = new Foo())
//{
// foo.Gar = "Gar";
// Console.WriteLine(foo.Gar);
//}
var anotherFoo = new Foo() { Gar = "Another gar" };
Console.WriteLine(anotherFoo.Gar);
anotherFoo.Dispose();
Console.ReadKey();
}
}
}
So, the final question, then, in summary is this:
Why is it that the call to Dispose
stops the compiler from being able to link assembly references?
I think we are now getting somewhere.