Время еще раз обратиться к более высоким умам.
Я наблюдаю очень странное явление. Как указано в заголовке, я получаю NullReferenceException при попытке создать EF ObjectContext, но я получаю исключение только в том случае, если я создаю контекст в операторе Using. Пробовал разными способами, но всегда одно и то же. И, конечно же, это код, который отлично работал до вчерашнего дня. Возможно, это связано с тем, что мое обновление Windows запустилось вчера утром.
Так или иначе...
Если я попробую это
using (var context = new Entities(Env.Instance.Connection))
{
//do a bunch of EF stuff
}
Я получаю NullReferenceException при создании моего ObjectContext. Здесь 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
}
Не имеет значения. Если я создаю контекст в операторе использования, я всегда получаю исключение NullReferenceException.
Я могу войти в код своего уровня данных и выйти из конструктора ObjectContext.
public Entities(string connectionString) : base(connectionString, "Entities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
Но как только я выхожу из конструктора, вылетает ошибка.
Мысли?
ИЗМЕНИТЬ
В самой простой итерации трассировка стека выглядит так
в IkaPlus.ViewModel.MainVM.ProcessMail3(отправитель объекта, DoWorkEventArgs e) в C:\SVN\IkaPlus\IkaPlus\ViewModel\MainVM.cs:Line 1371.
в IkaPlus.ViewModel.MainVM.RefillQueues() в C: \SVN\IkaPlus\IkaPlus\ViewModel\MainVM.cs:строка 832.
В идеале 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\""))
{
}
}
Оператор using в RefillQueues работает, а оператор using в ProcessMail3 — нет.
ИЗМЕНИТЬ 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. Нет запущенных фоновых рабочих.
ИЗМЕНИТЬ 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
}
Я не удосужился включить другие строки кода, потому что я перешагивал через них, когда вводил метод. Voodoo teching, я обнаружил, что если я закомментирую строку, которая создает мой CiCConnector (не должно иметь значения), мой оператор использования после того, как он будет работать нормально. Если строка НЕ закомментирована, независимо от того, дошел ли я до этой строки кода или нет, оператор 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\""))
{
}
}
Оператор using в первом методе работает нормально, но во втором методе он ломается.
пожать плечами Ваше предположение так же верно, как и мое. Наверное лучше. Думаю, я просто сочту это за странность и просто не буду использовать оператор using. Но, если у кого-то есть понимание, я был бы рад узнать, что, черт возьми, здесь происходит.
Entities
, иначе он будет иметь что-то вродеEntities..ctor
. Запустите только этотusing (var context = new Entities(Env.Instance.ConnectionString)) { // do nothing }
из чистого/обычного метода. Если он работает нормально, это не блок использования, а метод, в котором вы находитесь. - person rism   schedule 12.11.2015innerException
равно нулю... в противном случае, конечно, сначала посмотрите туда. - person rism   schedule 12.11.2015NullReferenceException
, должен быть довольно сильной подсказкой. Как я уже сказал выше, просто исключите это с помощью быстрого рефакторинга или иного модульного теста. - person rism   schedule 12.11.2015private void ProcessMail2()
, получится? Илиprivate void Processxyz()
- person rism   schedule 12.11.2015OnContextCreated
где-то мешает? - person Gert Arnold   schedule 18.11.2015