簡體   English   中英

任何ToList()的EF6 NullReferenceException

[英]EF6 NullReferenceException with any ToList()

使用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; }
}

什么可能導致這種行為?

編輯:當調用.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

編輯2:

經過實驗,我把它縮小到對dbCtx.Database.CompatibleWithModel(bool)的調用。 提供的參數是真還是假都沒有區別。 當我評論它時,代碼中不會引發NullReferenceException。 我不明白為什么 調用dbCtx.Database.Exists()工作正常。 另外, dbCtx.Database.Initialize(false); 還可靠地產生錯誤(不是在callsite,而是在xyz.ToList()上)。

據我所知,兩個表達式(帶括號和不帶括號)絕對等效,不可能導致不同的行為。 您可以通過查看生成的IL代碼來檢查(這里是如何: 一個簡單的IL代碼檢查工具 )。 在像這樣的模糊案例中,我通常會懷疑某種形式的多線程是罪魁禍首。 嘗試將有問題的代碼隔離到最低限度,看看你是否仍然能夠重現這一點。

我找到了一個決議。 據我所知,當從IDatabaseInitializer的子類的InitializeDatabase()方法的范圍之外調用某些方法(如Database.Initialize()Database.CompatibleWithModel()時,會導致這種情況。 也許這些方法有一些未知的副作用..?

我將包含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);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM