Я пытаюсь заполнить GridView
Entity Frameworkm, но каждый раз получаю следующую ошибку:
«Средство доступа к свойству LoanProduct на объекте COSIS_DAL.MemberLoan вызвало следующее исключение: экземпляр ObjectContext был удален и больше не может использоваться для операций, требующих подключения».
Мой код:
public List<MemberLoan> GetAllMembersForLoan(string keyword)
{
using (CosisEntities db = new CosisEntities())
{
IQueryable<MemberLoan> query = db.MemberLoans.OrderByDescending(m => m.LoanDate);
if (!string.IsNullOrEmpty(keyword))
{
keyword = keyword.ToLower();
query = query.Where(m =>
m.LoanProviderCode.Contains(keyword)
|| m.MemNo.Contains(keyword)
|| (!string.IsNullOrEmpty(m.LoanProduct.LoanProductName) && m.LoanProduct.LoanProductName.ToLower().Contains(keyword))
|| m.Membership.MemName.Contains(keyword)
|| m.GeneralMasterInformation.Description.Contains(keyword)
);
}
return query.ToList();
}
}
protected void btnSearch_Click(object sender, ImageClickEventArgs e)
{
string keyword = txtKeyword.Text.ToLower();
LoanController c = new LoanController();
List<COSIS_DAL.MemberLoan> list = new List<COSIS_DAL.MemberLoan>();
list = c.GetAllMembersForLoan(keyword);
if (list.Count <= 0)
{
lblMsg.Text = "No Records Found";
GridView1.DataSourceID = null;
GridView1.DataSource = null;
GridView1.DataBind();
}
else
{
lblMsg.Text = "";
GridView1.DataSourceID = null;
GridView1.DataSource = list;
GridView1.DataBind();
}
}
Ошибка упоминает LoanProductName
столбец Gridview
. Упоминается: я использую C #, ASP.net, SQL-Server 2008 в качестве серверной БД.
Я новичок в Entity Framework. Я не могу понять, почему я получаю эту ошибку. Кто-нибудь может мне помочь?
c#
asp.net
entity-framework
Бырсан
источник
источник
query.Include("SomeOtherTable")
db.MemberLoans.Include("LoanProduct").OrderByDescending()
проверить синтаксис, потому что передо мной нет VS.db.MemberLoans.Include("LoanProduct").Include("SomeOtherTable)
. Проверьте ответы @Tragedian и @lazyberezovskyОтветы:
По умолчанию Entity Framework использует отложенную загрузку для свойств навигации. Вот почему эти свойства должны быть помечены как виртуальные - EF создает прокси-класс для вашей сущности и переопределяет свойства навигации, чтобы разрешить отложенную загрузку. Например, если у вас есть эта сущность:
Entity Framework вернет прокси, унаследованный от этой сущности, и предоставит экземпляр DbContext этому прокси, чтобы позже разрешить ленивую загрузку членства:
Итак, у объекта есть экземпляр DbContext, который использовался для загрузки объекта. Это твоя проблема. Вы
using
заблокировали использование CosisEntities. Который удаляет контекст перед возвратом сущностей. Когда позже какой-то код пытается использовать свойство навигации с отложенной загрузкой, он терпит неудачу, потому что в этот момент контекст удаляется.Чтобы исправить это поведение, вы можете использовать активную загрузку свойств навигации, которые вам понадобятся позже:
Это предварительно загрузит все членства, и ленивая загрузка не будет использоваться. Подробнее см. Статью Загрузка связанных объектов на MSDN.
источник
db.MemberLoans.Include(m => m.Membership).Include(m => m.LoanProduct).OrderByDescending(m => m.LoanDate);
, это сгенерирует запрос JOIN и вернет все данные сразу.CosisEntities
Класс СВОЙDbContext
. Когда вы создаете контекст вusing
блоке, вы определяете границы для своей операции, ориентированной на данные.В своем коде вы пытаетесь выдать результат запроса из метода, а затем завершить контекст внутри метода. Операция, которой вы передаете результат, затем пытается получить доступ к объектам, чтобы заполнить представление сетки. Где-то в процессе привязки к сетке осуществляется доступ к свойству с отложенной загрузкой, и Entity Framework пытается выполнить поиск для получения значений. Это не удается, потому что связанный контекст уже закончился.
У вас две проблемы:
При привязке к сетке вы загружаете объекты с ленивой загрузкой. Это означает, что вы выполняете множество отдельных операций запроса к SQL Server, которые все замедлят. Вы можете решить эту проблему, либо настроив связанные свойства с готовностью загружаться по умолчанию, либо попросив Entity Framework включить их в результаты этого запроса с помощью
Include
метода расширения.Вы преждевременно завершаете свой контекст: a
DbContext
должен быть доступен во всей выполняемой единице работы, удаляя его только тогда, когда вы закончите с текущей работой. В случае ASP.NET единицей работы обычно является обрабатываемый HTTP-запрос.источник
Нижняя граница
Ваш код получил данные (объекты) через entity-framework с включенной отложенной загрузкой, и после удаления DbContext ваш код ссылается на свойства (связанные / отношения / объекты навигации), которые не были явно запрошены.
Более конкретно
С
InvalidOperationException
этим сообщением всегда означает одно и то же: вы запрашиваете данные (сущности) из entity-framework после удаления DbContext.Простой случай:
(эти классы будут использоваться для всех примеров в этом ответе, и предполагается, что все свойства навигации были настроены правильно и имеют связанные таблицы в базе данных)
Последняя строка выбрасывает
InvalidOperationException
потому что dbContext не отключил ленивую загрузку, и код обращается к свойству навигации Pet после того, как Context был удален с помощью оператора using.Отладка
Как вы находите источник этого исключения? Помимо просмотра самого исключения, которое будет выброшено именно в том месте, где оно возникает, применяются общие правила отладки в Visual Studio: установите стратегические точки останова и проверьте свои переменные. , либо наведя указатель мыши на их имена, открыв ( Быстро) Окно просмотра или использование различных панелей отладки, таких как Локальные и Авто.
Если вы хотите узнать, где установлена или не установлена ссылка, щелкните ее имя правой кнопкой мыши и выберите «Найти все ссылки». Затем вы можете разместить точку останова в каждом месте, которое запрашивает данные, и запустить свою программу с подключенным отладчиком. Каждый раз, когда отладчик прерывается в такой точке останова, вам необходимо определить, должно ли быть заполнено ваше свойство навигации или необходимы ли запрашиваемые данные.
Способы избежать
Отключить отложенную загрузку
Плюсы: вместо исключения InvalidOperationException свойство будет иметь значение null. Доступ к свойствам null или попытка изменить свойства этого свойства вызовет исключение NullReferenceException .
Как явно запросить объект при необходимости:
В предыдущем примере Entity Framework материализует Pet в дополнение к Person. Это может быть выгодно, потому что это единственный вызов базы данных. (Однако также могут быть огромные проблемы с производительностью в зависимости от количества возвращаемых результатов и количества запрошенных свойств навигации, в этом случае не будет никакого снижения производительности, поскольку оба экземпляра представляют собой только одну запись и одно соединение).
или
В предыдущем примере Entity Framework материализует Pet независимо от Person, выполняя дополнительный вызов базы данных. По умолчанию Entity Framework отслеживает объекты, полученные из базы данных, и при обнаружении соответствующих свойств навигации автоматически заполняет эти сущности магическим способом. В этом случае , так как
PetId
наPerson
объект совпадает сPet.Id
, Entity Framework будет назначитьPerson.Pet
наPet
значение , извлеченное, прежде чем значение присваивается переменной для домашних животных.Я всегда рекомендую этот подход, поскольку он заставляет программистов понимать, когда и как код запрашивает данные через Entity Framework. Когда код генерирует исключение с нулевой ссылкой для свойства объекта, вы почти всегда можете быть уверены, что не запрашивали эти данные явно.
источник
Это очень поздний ответ, но я решил проблему, отключив ленивую загрузку:
источник
В моем случае я передавал все модели «Пользователи» в столбец, и он не отображался правильно, поэтому я просто передал «Users.Name» и исправил его.
источник
Большинство других ответов указывают на нетерпеливую загрузку, но я нашел другое решение.
В моем случае у меня был объект EF
InventoryItem
с коллекциейInvActivity
дочерних объектов.И поскольку я извлекал из коллекции дочерних объектов вместо контекстного запроса (с
IQueryable
),Include()
функция была недоступна для реализации активной загрузки. Поэтому вместо этого я решил создать контекст, в котором я использовал,GetLatestActivity()
иattach()
возвращаемый объект:Таким образом, вы не застряли в нетерпеливой загрузке.
источник
Если вы используете ASP.NET Core и задаетесь вопросом, почему вы получаете это сообщение в одном из методов асинхронного контроллера, убедитесь, что вы возвращаете,
Task
а неvoid
- ASP.NET Core удаляет внедренные контексты.(Я отправляю этот ответ, так как этот вопрос занимает одно из первых мест в результатах поиска по этому сообщению об исключении, и это тонкая проблема - возможно, это полезно для людей, которые ищут его в Google.)
источник