又到了请教高手的时候了。
我遇到了一个很奇怪的现象。正如标题所述,当我尝试创建一个 EF ObjectContext 时,如果我在 Using 语句中创建上下文,我会得到 NullReferenceException 异常。我尝试了各种不同的方法,但结果总是一样。当然,这段代码昨天之前都能够正常工作。可能与我昨天早上运行的 Windows 更新有关。
无论如何...
如果我尝试这样做
using (var context = new Entities(Env.Instance.Connection))
{
//do a bunch of EF stuff
}
我在创建我的ObjectContext时遇到了NullReferenceException。这里的Env.Instance.Connection是在程序早期创建的EntityConnection。我已经逐步检查以确保实例和EntityConnection都存在。如果我这样做
var context = new Entities(Env.Instance.Connection);
//do a bunch of EF stuff
context.Dispose();
一切都正常。
我已经尝试过。
using (var context = new Entities(Env.Instance.ConnectionName)) //the name of a connection string in my App.Config
{
//do a bunch of EF stuff
}
我已经尝试过了
using (var context = new Entities(Env.Instance.ConnectionString)) //the actual connection string
{
//do a bunch of 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\""))
{
//do a bunch of EF stuff
}
无所谓。如果我在using语句内创建上下文,我总是会收到NullReferenceException。
我可以进入我的数据层代码并退出ObjectContext构造函数。
public Entities(string connectionString) : base(connectionString, "Entities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
但是,一旦我退出构造函数,就会抛出错误。
有什么想法?
编辑
在最简单的迭代中,堆栈跟踪如下:
在C:\SVN\IkaPlus\IkaPlus\ViewModel\MainVM.cs:Line 1371处的IkaPlus.ViewModel.MainVM.ProcessMail3(Object sender, DoWorkEventArgs e)
在C:\SVN\IkaPlus\IkaPlus\ViewModel\MainVM.cs:Line 832处的IkaPlus.ViewModel.MainVM.RefillQueues()。
理想情况下,ProcessMail3应该由BackgroundWorker调用,因此它的签名是这样的,但目前,我正在使用空参数从主线程调用它。
澄清一下,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\""))
{
}
}
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\""))
{
}
}
同样的结果。在第一个方法中使用语句是有效的。在第二种方法中使用语句会抛出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
}
由于我输入方法时一直在步进,所以我没有费心去包含其他代码行。我发现,如果我注释掉创建 CiCConnector 的那行代码(不应该相关),那么之后的 using 语句就能正常运行了。即使我实际上没有到达那行代码,只要这行代码没有被注释,using 语句就无法工作。如果我在创建字符串的那行代码上设置断点,然后跳过下一行代码,直接到达 using 语句,那么我就会得到 NullReferenceException 异常。如果我注释掉 CiCConnector 那行代码并做同样的事情,则 using 语句可以正常使用。另外,如果不用 using 语句而是手动创建 ObjectContext,然后稍后手动释放它,那么不管有没有 CiCConnector 那行代码,所有东西都可以正常运行。这一切都非常奇怪。
第四次编辑
奇怪的是,如果把 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\""))
{
}
}
第一种方法中的using语句工作正常,但在第二种方法中它会出问题。
耸肩你的猜测和我的一样好。可能更好。我想我会把它归结为一个奇怪的事情,并简单地不使用using语句。但是,如果有人有任何见解,我会很高兴知道到底发生了什么。
OnContextCreated
在某个地方干扰了? - Gert Arnold