在Using语句中创建ObjectContext时出现NullReferenceException

Tro*_*ier 12 c# entity-framework using-statement nullreferenceexception objectcontext

时间再次吸引更多的思想.

我遇到了一个非常奇怪的现象.正如标题所述,我在尝试创建EF ObjectContext时遇到NullReferenceException,但是如果我在Using语句中创建上下文,我只会得到异常.我尝试了各种不同的方式,但总是一样.当然,这是直到昨天才能正常工作的代码.昨天早上我的Windows Update运行可能是相关的.

无论如何...

如果我试试这个

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

我在创建ObjectContext时得到NullReferenceException.这里的Env.Instance.Connection是在程序的早期创建的EntityConnection.我已经介入以确保实例和EntityConnection都存在.

如果我这样做的话

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

一切正常.

我试过了

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

我试过了

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

我甚至试过了

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
}
Run Code Online (Sandbox Code Playgroud)

无所谓.如果我在using语句中创建上下文,我总是会得到一个NullReferenceException.

我可以进入我的数据层的代码,然后退出ObjectContext构造函数

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

但是,一旦我退出构造函数,就会抛出错误.

思考?

编辑

在绝对最简单的迭代中,堆栈跟踪看起来像这样

在C:\ SVN\IkaPlus\IkaPlus\ViewModel\MainVM.cs中的IkaPlus.ViewModel.MainVM.ProcessMail3(对象发送者,DoWorkEventArgs e):行1371.
在C:\ SVN \中的IkaPlus.ViewModel.MainVM.RefillQueues() IkaPlus\IkaPlus\ViewModel\MainVM.cs:第832行.

理想情况下,ProcessMail3将从BackgroundWorker调用,因此它的签名,但此刻,我从主线程调用它与null参数.

为了澄清,ProcessMail3方法旨在从后台工作程序调用,这就是为什么它的签名中有sender和DoWorkEventArgs.但此刻,我直接从主线程调用它,如下所示:ProcessMail3(null,null)

我认为rism是有目共睹的.如果我这样做

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\""))
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

RefillQueues中的using语句有效,但ProcessMail3中的using语句不起作用.

编辑2

为了进一步简化,我删除了违规方法签名中的参数.所以,现在我正在打电话

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\""))
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

结果相同.在第一种方法中使用语句有效.在第二个方法中使用语句会抛出NullReferenceException.没有运行BackgroundWorkers.

编辑3

所以,我似乎找到了导致我错误的原因,尽管我仍然无法解释.

所以,我的ProcessMail3方法实际上看起来像这样(我把它重命名为EatCookies因为...我喜欢吃饼干.)

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
}
Run Code Online (Sandbox Code Playgroud)

我没有费心去包含其他代码行,因为当我进入方法时,我一直在踩它们.Voodoo teching,我发现如果我注释掉创建我的CiCConnector的行(不应该是相关的)我的using语句就可以了.如果未注释掉行,无论我是否实际到达该行代码,using语句都不起作用.如果我在创建字符串的行上设置断点,并跳过下一行,直接转到我的using语句,我得到NullReferenceException.如果我注释掉CiCConnector行并执行相同的操作,则using语句可以正常工作.而且,再次,如果不是使用using语句,我只是创建我的ObjectContext然后手动处理它,无论CiCConnector行如何都可以正常工作.这一切都很奇怪.

编辑4

奇怪的是,CiCConnector行如果放在第一个方法中,则不会引起奇怪的行为.所以,如果我这样做

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\""))
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

第一种方法中的using语句工作正常,但在第二种方法中它会中断.

耸耸肩你的猜测和我一样好.可能更好.我想我只是把它当作一个奇怪的,并且根本不使用using语句.但是,如果有人有任何见解,我会很高兴找到这里发生了什么.

Ste*_*ley 1

EF 为您管理处置,因此您自己使用或显式处置它有点多余

\n\n

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

\n\n

文章摘录

\n\n
\n

在与 EF 团队的开发人员交谈之前,我的答案始终是响亮的 \xe2\x80\x9co 当然!\xe2\x80\x9d。但 DbContext\xe2\x80\x99 则不然。您不需要在 DbContext 对象上调用 Dispose 。尽管它确实实现了 IDisposable,但它只是实现了它,因此您可以在某些特殊情况下调用 Dispose 作为保护措施。默认情况下,DbContext 会自动为您管理连接。阅读全文以了解完整的故事,并了解 EF 开发人员对此有何评论。

\n
\n