首页 文章

任何ToList()的EF6 NullReferenceException

提问于
浏览
7

使用C#,.NET 4.5.2,Entity Framework 6.1.3和System.Linq我遇到了一个令人困惑的异常 . 异常本身似乎没有包含有用的信息来确定它被提出的原因 .

执行时的以下代码行导致NullReferenceException: dbCtx.Customers.ToList();

但是,以下行无异常运行并返回正确的结果: (dbCtx.Customers).ToList();

首先运行括号括起的表达式将允许两个表单无异常地执行:

var result1 = (dbCtx.Customers).ToList();
var result2 = dbCtx.Customers.ToList();

我还要注意添加实体按预期工作:

dbCtx.Customers.Add(new Customer() { Enabled = true, Name = "Test" });

客户实体类:

public sealed class Customer : BaseEntity
{
    public bool Enabled { get; set; }

    [Required]
    public string Name { get; set; }
}

BaseEntity类:

public abstract class BaseEntity
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
}

DbContext类:

public class MyDbContext : DbContext
{
    public MyDbContext() : base(@"Server=.\SQLExpress;Database=MyDatabase;Trusted_Connection=Yes;")
    {
        Configuration.LazyLoadingEnabled = true;
    }

    public virtual DbSet<Customer> Customers { get; set; }
}

什么可能导致这种行为?

EDIT: 当调用.ToList(),. Count()等任何实体时,会出现此问题 .

例外细节:

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:

经过实验,我把它缩小到了对 dbCtx.Database.CompatibleWithModel(bool) 的调用 . 提供的参数是真还是假都没有区别 . 当我评论它时,代码中不会引发NullReferenceException . 我不知道为什么 . 调用 dbCtx.Database.Exists() 工作正常 . 此外, dbCtx.Database.Initialize(false); 还可靠地产生错误(不是在callsite,而是在xyz.ToList()上) .

2 回答

  • 0

    据我所知,两个表达式(带括号和不带括号)绝对等效,不可能导致不同的行为 . 您可以通过查看生成的IL代码来检查(这里是如何:A tool for easy IL code inspection) . 在像这样的模糊案例中,我通常会怀疑某种形式的多线程是罪魁祸首 . 尝试将有问题的代码隔离到最低限度,看看是否仍然可以重现这一点 .

  • 0

    我找到了一个决议 . 据我所知,当 Database.Initialize()Database.CompatibleWithModel() 等某些方法从 IDatabaseInitializer 的子项的 InitializeDatabase() 方法范围之外调用时,会导致它 . 也许这些方法有一些未知的副作用..?

    我将包含一个示例专业化 IDatabaseInitializer ,只是为了清楚其他任何可能遇到此问题的人:

    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);
        }
    }
    

相关问题