在线投票应用中Question与Answer模型关联的技术问题
解决在线投票系统中关联Question与Answer的问题
看起来你在搭建在线投票系统的时候,卡在了Question和Answer的关联上——别担心,这是EF关联实体时很常见的场景,我给你分两种最常见的业务场景来讲解解决方案:
场景1:创建Question时同时添加关联的Answers
如果是用户提交一个新问题的同时,也提交了对应的选项答案,那你可以直接在构建Question实体时,把Answer关联进去,EF会自动帮你处理外键赋值:
[HttpPost] public ActionResult CreateQuestion(QuestionCreateViewModel viewModel) { if (!ModelState.IsValid) { return View(viewModel); } // 初始化Question实体 var newQuestion = new Question { Text = viewModel.QuestionText, StartDate = viewModel.StartDate, EndDate = viewModel.EndDate, IsActive = viewModel.IsActive, Answers = new List<Answer>() // 先初始化答案列表 }; // 遍历用户提交的答案文本,创建Answer并关联到Question foreach (var answerText in viewModel.AnswerTexts) { var newAnswer = new Answer { Text = answerText // 这里不需要手动赋值QuestionId! // 只要把Answer加入Question的Answers列表,EF会在保存时自动填充外键 }; newQuestion.Answers.Add(newAnswer); } // 保存到数据库 db.Questions.Add(newQuestion); db.SaveChanges(); return RedirectToAction("Index"); }
小提示:如果你的Question.Id是数据库自动生成的(比如Identity自增列),千万别手动去赋值newAnswer.QuestionId = newQuestion.Id——这时候newQuestion还没保存,Id是默认值(比如0),EF会在SaveChanges的时候自动完成外键的赋值工作。
场景2:给已存在的Question添加新的Answer
如果是用户后续给已发布的问题追加答案,那你需要先从数据库取出对应的Question,再关联新Answer:
[HttpPost] public ActionResult AddAnswer(int questionId, string answerText) { // 从数据库获取目标Question,记得预加载Answers列表避免延迟加载问题 var targetQuestion = db.Questions .Include(q => q.Answers) .FirstOrDefault(q => q.Id == questionId); if (targetQuestion == null) { return HttpNotFound("找不到对应的投票问题"); } // 创建新Answer并手动关联QuestionId var newAnswer = new Answer { Text = answerText, QuestionId = questionId // 直接用传入的questionId赋值 }; // 两种关联方式选一种即可: // 方式1:添加到Question的Answers列表 targetQuestion.Answers.Add(newAnswer); // 方式2:直接添加到DbContext的Answers集合 // db.Answers.Add(newAnswer); db.SaveChanges(); return RedirectToAction("Details", new { id = questionId }); }
关键注意:这里用Include(q => q.Answers)是为了预加载答案列表,避免后续访问targetQuestion.Answers时触发EF的延迟加载,导致不必要的数据库查询或者上下文异常。
额外要注意的实体配置
确保你的实体类导航属性配置正确,这样EF才能正确识别关联关系:
public class Question { public int Id { get; set; } public string Text { get; set; } public List<Answer> Answers { get; set; } public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } public bool IsActive { get; set; } // 建议加上无参构造函数,初始化Answers列表 public Question() { Answers = new List<Answer>(); } } public class Answer { public int Id { get; set; } public int QuestionId { get; set; } public string Text { get; set; } public int Votes { get; set; } // 可选:添加双向导航属性,方便从Answer反向查询Question public virtual Question Question { get; set; } }
内容的提问来源于stack exchange,提问作者Dorin Munreanu
相关产品推荐
相关产品推荐

