Using C#, .NET 4.5.2, Entity Framework 6.1.3 and System.Linq I have encountered a confusing exception. The exception itself does not seem to contain useful information to determined why it is being raised.
The following line of code when executed results in a NullReferenceException:
dbCtx.Customers.ToList();
However, the following line runs without exception and returns the correct result:
(dbCtx.Customers).ToList();
Running the parenthesis surrounded expression first will allow both forms to execute without exception:
var result1 = (dbCtx.Customers).ToList();
var result2 = dbCtx.Customers.ToList();
I would also like to note that adding entities works as expected:
dbCtx.Customers.Add(new Customer() { Enabled = true, Name = "Test" });
Customer entity class:
public sealed class Customer : BaseEntity
{
public bool Enabled { get; set; }
[Required]
public string Name { get; set; }
}
BaseEntity class:
public abstract class BaseEntity
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
}
DbContext class:
public class MyDbContext : DbContext
{
public MyDbContext() : base(@"Server=.\SQLExpress;Database=MyDatabase;Trusted_Connection=Yes;")
{
Configuration.LazyLoadingEnabled = true;
}
public virtual DbSet<Customer> Customers { get; set; }
}
What could possibly be causing this behavior?
EDIT: This problem occurs with any entity when anything like .ToList(), .Count(), etc is invoked.
Exception Details:
System.NullReferenceException occurred
HResult=0x80004003
Message=Object reference not set to an instance of an object.
Source=EntityFramework
StackTrace:
at System.Data.Entity.Internal.Linq.InternalSet`1.get_Expression()
at System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Expression()
at MyProjTests.Test1.Test(MyDbContext dbCtx) in E:\ProgrammingProjects\WorkInProgress\MyProjRoot\MyProjTests\Test1.cs:line 51
at MyProjTests.Test1.TestMethod1() in E:\ProgrammingProjects\WorkInProgress\MyProjRoot\MyProjTests\Test1.cs:line 43
EDIT 2:
After experimentation I've narrowed it down to a call to dbCtx.Database.CompatibleWithModel(bool)
. Whether the argument supplied is true or false makes no difference. When I commented it out no NullReferenceException is raised later in the code. I have no idea why. Calling dbCtx.Database.Exists()
works fine.
In addition, dbCtx.Database.Initialize(false);
Also reliably produces the error (not at callsite, but on xyz.ToList()).
For all I know the two expressions (with and without brackets) are absolutely equivalent and cannot possibly cause a different behavior. You can check that by looking at the IL code generated (here's how: A tool for easy IL code inspection). In obscure cases like this, I would generally suspect some form of multithreading to be the culprit. Try isolating the offending code to the bare minimum and see if you can still reproduce this.
I have found a resolution. As best as I can tell, it is caused when certain methods like Database.Initialize()
and Database.CompatibleWithModel()
are called from outside the scope of a InitializeDatabase()
method of a child of IDatabaseInitializer
. Perhaps there is some unknown side effect involved with those methods..?
I'll include an example specialization of IDatabaseInitializer
just for clarity for anyone else who may stumble across this problem:
public class CreateOrMigrateDatabaseInitializer<TContext, TConfiguration>
: CreateDatabaseIfNotExists<TContext>, IDatabaseInitializer<TContext>
where TContext : DbContext
where TConfiguration : DbMigrationsConfiguration<TContext>, new()
{
void IDatabaseInitializer<TContext>.InitializeDatabase(TContext context)
{
if (context.Database.Exists())
{
if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false))
{
var migrationInitializer = new MigrateDatabaseToLatestVersion<TContext, TConfiguration>(true);
migrationInitializer.InitializeDatabase(context);
}
}
base.InitializeDatabase(context);
}
}
User contributions licensed under CC BY-SA 3.0