次の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プロパティにアクセスすると、null参照例外が発生します。 Include( "QuestionType")を使用していますが、機能していないようです。私は何を間違えていますか?
編集:遅延読み込みをオンにしている場合、null参照例外はスローされません。
編集:Include()は、次のことを行うと機能しているようです:
var questions = db.Questions.Include("QuestionType").Select(q => q);
別のエンティティを述語すると、インクルードが失敗するようです。 Includeを使用する場合、許可されませんか?私のクエリがこのことを機能させない原因は何ですか?
問題は、Linq式のサブクエリに関連している可能性があります。 here で説明されているように、副選択、グループ化、および射影により、Include
の積極的な読み込みがサイレントに失敗することがあります here (Diego Vegaの回答をどこかで参照してください)スレッドの途中で)。
これらの投稿で説明されている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);
}
(または、投稿に記載されている拡張メソッドを使用します。)
リンクされた投稿を正しく理解していれば、必ずしもそれが現在動作する(おそらく動作しない)とは限りませんが、問題の詳細を示す例外が表示されます。
「System.Data.Entity」を追加すると、IQueryableでIncludeを呼び出すことができます。
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");
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();
}
そのため、問題はコードの順序でした。エンティティフレームワークは、エンティティがEntityState.Deleted
としてマークされるとすぐにメモリ内のナビゲーションプロパティを無効にするようです。したがって、コードでexistingUserTopic.Topic
にアクセスするには、existingUserTopic
を削除済みとしてマークする前にアクセスする必要があります。
この質問は「Entity Framework Include not working」の検索結果の上位であるため、@ Dismissileの元の投稿には関係ないものの、他のいくつかの可能性について言及します。
ケース感度
SQL Server(および場合によっては他のデータベースプラットフォーム)は、大文字と小文字を区別しない方法で動作することがよくあります。したがって、主キー値ABC1がある場合、データベースは有効な外部キー値としてABC1、abc1、AbC1などを受け入れます。ただし、.Net文字列比較ではデフォルトで大文字と小文字が区別されるため、.Includeが追加のSQLを生成して追加の値をEFにプルしている場合でも、キーに大文字と小文字の違いがあると、子オブジェクトの設定に失敗する可能性があります。これについてはもう少し詳しく説明します SO question 良いリンクがいくつかあります。主キーと外部キーの列に大文字と小文字を区別する照合を使用すると、.Includeエラーのこの原因のリスクを減らすことができます。
トレーリングスペース
これは、なぜ.Includeが機能しなかったのかを解明しようとして私の人生の1日を失った原因です。 SQL Server(および場合によっては他のデータベースプラットフォーム)は、文字列比較の末尾のスペースを無視することがよくあります。したがって、主キー値(引用符を含まない) "ABC"(末尾のスペース1つ)がある場合、データベースは "ABC"(スペース1つ)、 "ABC"(スペースなし)、 "ABC"(スペース2つ)を受け入れます。 )など、有効な外部キー値として。ただし、.Net文字列比較は末尾のスペースを無視しないため、.Includeが追加の値をEFにプルするための追加のSQLを生成している場合でも、キーの末尾のスペースに違いがあると、子オブジェクトの設定に失敗する可能性があります。 SQL Serverの動作については、この MSサポート ページで説明しています。慎重なデータ管理以外の障害を含める、つまり、ユーザーに外部キー値の入力を許可しない-ドロップダウンリストを使用する、またはユーザー入力を宗教的に使用するなど、この種のエラーを防ぐための適切な戦略を立てていません。