我正在使用Entity Framework 5和MVC 4,使用.NET 4.5使用Code First迁移.我在两个实体之间有1到0或1关系的外键.当我尝试为Jogger创建记录时,一切都会爆炸.我收到的错误消息是:
>外键是空引用
> dbo.Jogger不存在
>未处理的异常……没有元数据.
当我运行EF Viewer时,导航关系是完美的.目前没有使用Fluent API代码.
用户类
[Key] [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] public int UserId { get; set; } public string UserName { get; set; } // Other properties public int? JoggerId { get; set; } public virtual Jogger Jogger { get; set; }
慢跑者班
[ForeignKey("UserId")] public int JoggerId { get; set; } public virtual UserProfile UserId { get; set; }
生成JoggerController时,它会为Get和Post方法生成此代码:
// GET: /Jogger/Create public ActionResult Create() { ViewBag.JoggerId = new SelectList(db.UserProfiles,"UserId","UserName"); return View(); } // // POST: /Jogger/Create [HttpPost] [ValidateAntiForgeryToken] public ActionResult Create(Jogger jogger) { if (ModelState.IsValid) { db.Jogger.Add(jogger); db.SaveChanges(); return RedirectToAction("Index"); } ViewBag.JoggerId = new SelectList(db.UserProfiles,"UserName",jogger.JoggerId); return View(jogger); }
在Jogger / Create视图中,根据生成的代码,没有JoggerId或UserId的字段.
通常,它在代码的(ModelState.IsValid)部分失败,其中Output显示JoggerId = 0和UserId = null.
我没有在asp.net网站上的Contoso大学教程中看到这种行为,我也查看了MSDN学习EF网站.我似乎无法解决这个问题.您的建议表示赞赏.
解决方法
经过多次试验和错误,我找到了一种方法,可以为外键分配一个值.
首先,我的关系设置不正确:UserProfile类不需要public int? GolferId代表导航属性.最后的课程如下:
用户资料
[Key] [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] public int UserId { get; set; } public string UserName { get; set; } // Navigation properties public virtual Jogger Jogger { get; set; }
慢跑者班
[Key] [ForeignKey("UserId")] public int JoggerId { get; set; } public string Pronation {get; set;} public virtual UserProfile UserId { get; set; }
这可以设置正确的关系,而无需任何Fluent API代码.
分配ForeignKey值有点棘手,我确信有比这更好的方法.
>我使用了FormCollection而不是其他定义的脚手架方法(id = 0).您还可以使用[Bind(Include =“field1,field2,field3”)]来确保发布正确的字段.
>到登录用户的UserId有很长的路要走,它利用了User.Identity.Name
> FormCollection允许我引用和保存其他字段,例如旋前
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Create(FormCollection values) { var jogger = new Jogger(); TryUpdateModel(jogger); var context = new TestContext(); var userqq = User.Identity.Name; var user = context.UserProfiles.SingleOrDefault(u => u.UserName == userqq); if (ModelState.IsValid) { jogger.JoggerId = user.UserId; jogger.Pronation = values["Pronation"]; db.Joggers.Add(jogger); db.SaveChanges(); return View(); } ViewBag.JoggerId = new SelectList(db.UserProfiles,jogger.JoggerId); return View(jogger); }
这根本不是很好,但确实有效.感谢@Moeri指出我正确的方向.