MVC5 Code-First模式下多对多关系数据种子填充报错求助
Let's figure out why you're hitting that null reference error when setting up the many-to-many relationship in your Seed method. The issue boils down to two common pitfalls with EF Code-First seed data and navigation properties:
1. Navigation Collections Aren't Initialized
First, your Diagnoses collection on the Cognition class (and vice versa) is declared but never initialized. Even though it's marked virtual for lazy loading, when you create a new Cognition instance manually, that collection starts as null. When you try to call Add() on a null collection, you get the "Object reference not set..." error.
Fix: Add constructors to your model classes to initialize the navigation collections:
public class Cognition { public int CognitionID { get; set; } public string CognitionText { get; set; } public virtual ICollection<Diagnosis> Diagnoses { get; set; } public virtual ICollection<SubDiagnosis> SubDiagnoses { get; set; } public Cognition() { // Initialize collections to avoid null references Diagnoses = new HashSet<Diagnosis>(); SubDiagnoses = new HashSet<SubDiagnosis>(); } } public class Diagnosis { public int DiagnosisID { get; set; } public string DiagnosisText { get; set; } public virtual ICollection<Cognition> Cognitions { get; set; } public virtual ICollection<SubCognition> SubCognitions { get; set; } public Diagnosis() { Cognitions = new HashSet<Cognition>(); SubCognitions = new HashSet<SubCognition>(); } }
2. Using Unattached Entities for Relationship Setup
When you use AddOrUpdate, EF might not be using the exact instances you stored in your diagnoses and cognitions arrays. If the entity already exists in the database, AddOrUpdate will attach the existing database entity to the context—not the new instance you created. This means your array's objects might not be tracked by EF, and their navigation collections might still be null (even if you fixed the constructor issue).
Fix: Fetch the tracked entities from the context before setting up the relationship:
protected override void Seed(NVD.DAL.NVDContext context) { // Add/update diagnoses var diagnoses = new[] { new Diagnosis { DiagnosisText = "Alzheimer's disease" }, new Diagnosis { DiagnosisText = "Mixed dementia" }, new Diagnosis { DiagnosisText = "Cerebrovascular disease" }, new Diagnosis { DiagnosisText = "Lewy body dementia" }, new Diagnosis { DiagnosisText = "Parkinson's disease (PD)" }, new Diagnosis { DiagnosisText = "Parkinson Plus (PSP/CBD/MSA)" }, new Diagnosis { DiagnosisText = "Huntington's disease" }, new Diagnosis { DiagnosisText = "Frontotemporal dementia" }, new Diagnosis { DiagnosisText = "Normal pressure Hydrocephalus (NPH)" }, new Diagnosis { DiagnosisText = "Other neurodegenerative disorder" }, new Diagnosis { DiagnosisText = "Alcohol" }, new Diagnosis { DiagnosisText = "Other non-neurodegenerative disorder" }, new Diagnosis { DiagnosisText = "Unknown" }, new Diagnosis { DiagnosisText = "SCD" }, new Diagnosis { DiagnosisText = "Psychiatric illness" }, new Diagnosis { DiagnosisText = "NPH" }, new Diagnosis { DiagnosisText = "Other" } }; context.Diagnoses.AddOrUpdate(r => r.DiagnosisText, diagnoses); // Add/update cognitions var cognitions = new[] { new Cognition { CognitionText = "Normal" }, new Cognition { CognitionText = "Significantly impaired" }, new Cognition { CognitionText = "Mild dementia" }, new Cognition { CognitionText = "Moderate dementia" }, new Cognition { CognitionText = "Severe dementia" } }; context.Cognitions.AddOrUpdate(r => r.CognitionText, cognitions); // Save first to ensure all entities are in the database/context context.SaveChanges(); // Fetch the tracked entities from the context var normalCognition = context.Cognitions.FirstOrDefault(c => c.CognitionText == "Normal"); var psychiatricDiagnosis = context.Diagnoses.FirstOrDefault(d => d.DiagnosisText == "Psychiatric illness"); // Set up the relationship only if both entities exist if (normalCognition != null && psychiatricDiagnosis != null) { normalCognition.Diagnoses.Add(psychiatricDiagnosis); context.SaveChanges(); } }
Why This Works
- Initializing the collections in the constructor ensures that every new instance of
CognitionorDiagnosishas a non-null collection to work with. - Fetching entities from the context after
SaveChanges()guarantees you're using the EF-tracked versions, which have properly initialized navigation collections (thanks to lazy loading or EF's internal initialization).
Give these changes a try, and your update-database command should run without the null reference error.
内容的提问来源于stack exchange,提问作者Nielsen

