Entity Framework Include() не работает
У меня есть следующий запрос EF:
TestEntities db = new TestEntities();
var questions = from q in db.Questions.Include("QuestionType")
from sq in db.SurveyQuestions
where sq.Survey == surveyTypeID
orderby sq.Order
select q;
foreach( var question in questions ) {
// ERROR: Null Reference Exception
Console.WriteLine("Question Type: " + question.QuestionType.Description);
}
Я получаю исключение с нулевой ссылкой, когда я обращаюсь к свойству QuestionType. Я использую Include ( "QuestionType" ), но он, похоже, не работает. Что я делаю неправильно?
Изменить. При запуске Lazy Loading он не выбрасывает исключение с нулевой ссылкой.
Изменить: Include() работает, когда я делаю следующее:
var questions = db.Questions.Include("QuestionType").Select(q => q);
Когда я предикация на отдельном объекте Include, похоже, терпит неудачу. Это запрещено при использовании Include? Как насчет моего запроса, потому что эта вещь не работает?
Ответы
Ответ 1
Проблема может быть связана с подзапросом в выражении Linq. Подсчеты, группировка и проекции могут привести к интенсивной загрузке с Include
, как это упоминалось здесь и более подробно объяснены здесь (см. ответы Диего Веги где-то в середине потока).
Хотя я не могу видеть, что вы нарушаете какие-либо правила, которые следует соблюдать при использовании Include
, как описано в этих сообщениях, вы можете попытаться изменить запрос в соответствии с рекомендацией:
var questions = from q in db.Questions
from sq in db.SurveyQuestions
where sq.Survey == surveyTypeID
orderby sq.Order
select q;
var questionsWithInclude = ((ObjectQuery)questions).Include("QuestionType");
foreach( var question in questionsWithInclude ) {
Console.WriteLine("Question Type: " + question.QuestionType.Description);
}
(Или используйте метод расширения, упомянутый в сообщениях.)
Если я правильно понимаю связанные ссылки, это не обязательно означает, что он будет работать сейчас (возможно, нет), но вы получите исключение, дающее более подробную информацию о проблеме.
Ответ 2
Добавьте "System.Data.Entity", и вы сможете вызвать Include on IQueryable:
var questions = from q in db.Questions
from sq in db.SurveyQuestions
where sq.Survey == surveyTypeID
orderby sq.Order
select q;
questions = questions.Include("QuestionType");
см.: Как я могу преобразовать DBQuery <T> к объекту ObjectQuery <T> ?
Ответ 3
Я столкнулся с этой проблемой Include(e => e.NavigationProperty)
не работая, но решение было иным, чем указано выше.
Проблемный код был следующим:
UserTopic existingUserTopic = _context.UserTopics
.Include(ut => ut.Topic)
.FirstOrDefault(t => t.UserId == currentUserId && t.TopicId == topicId);
if (existingUserTopic != null)
{
var entry = _context.Entry(existingUserTopic);
entry.State = EntityState.Deleted;
if (existingUserTopic.Topic.UserCreated)
{
var topicEntry = _context.Entry(existingUserTopic.Topic);
entry.State = EntityState.Deleted;
}
await _context.SaveChangesAsync();
}
Итак, проблема заключалась в порядке кода. Entity Framework, по-видимому, аннулирует свойства навигации в памяти, как только объект помечен как EntityState.Deleted
. Поэтому для доступа к existingUserTopic.Topic
в моем коде, я должен сделать это, прежде чем удалять отметку existingUserTopic
.