分配UserId到外键= null
我使用实体框架5和MVC 4,.NET 4.5使用Code First迁移。我有两个实体之间的外键以1到0或1的关系。当我尝试为慢跑者创造记录时,一切都会爆炸。我得到的要么是错误消息:分配UserId到外键= null
- 外键为空引用
- dbo.Jogger不存在
- 未处理的异常......没有元数据。
当我运行EF浏览器的导航关系是完美的。目前没有使用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, "UserId", "UserName", jogger.JoggerId);
return View(jogger);
}
在Jogger/Create视图中,根据生成的代码,没有用于JoggerId或UserId的字段。
通常,它在输出显示JoggerId = 0和UserId = null的代码的(ModelState.IsValid)部分上失败。
我在asp.net网站上的Contoso University教程上没有看到这种行为,我也查看了MSDN学习EF网站。我似乎无法解决这个问题。你的建议表示赞赏。
回答:
多的试验和错误之后,我发现,工作分配的一种方式外键一个值。
首先,我的关系设置不正确:UserProfile类不需要public int? GolferId代表导航属性。 final类看起来如下:
用户配置
[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; }
这样的设置,而无需任何流利的API代码的正确关系。
要分配ForeignKey的值是有点麻烦,我敢肯定有做比这更好的方法。
- 而不是定义(ID = 0)的另一方法的脚手架,我使用的的FormCollection。您也可以使用[绑定(包括=“字段1,字段2,字段3”),以确保正确的字段被公布。
- 有很长的路由到登录用户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, "UserId", "UserName", jogger.JoggerId);
return View(jogger);
}
这并不漂亮的所有,但它确实工作。感谢@Moeri指引我着正确的方向发展。
回答:
这是你的错误:
public virtual UserProfile UserId { get; set; }
实体框架代码优先工作与公约,其中之一是基于名称的约定。这意味着,如果你有一个属性“用户ID”,它会寻找一表“用户”,并将其配置为外键,它的表。 我认为这是炸毁,因为你给你的导航属性的传统用于外键属性的名称。
工作的正确方法是:
public virtual int? UserId { get; set; } public virtual User User { get; set; }
如果你想你的财产被称为“UserProfileId”,你将不得不使用“ForeignKey的”属性或流利配置语法让实体框架知道这是一个外键:
public virtual int? UserProfileId{ get; set; } [ForeignKey("UserProfileId")
public virtual User User { get; set; }
或用流利的语法(你写这在您的语境OnModelCreating方法,或在一个单独的类,从EntityTypeConfiguration继承):
HasRequired(j => j.User).WithMany().HasForeignKey(i => i.UserProfileId)
编辑:我只注意到你的用户表实际上是所谓的用户配置,这有点使我的回答毫无意义的后半段。尽管如此,我会放弃它,因为它可以是教育。
回答:
的错误是在数据库模型。 实体框架代码首先总是需要一个一对一的关系配置。 Code First无法确定哪些类是这些情况下的依赖项。
1-在你的慢跑类添加属性:
public virtual User User { get; set; }
2 - 在你OnModelCreating添加方法:
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
// One to One relationship
modelBuilder.Entity<User>()
.HasOptional(t => t.Jogger)
.WithOptionalDependent(m => m.User);
}
以上是 分配UserId到外键= null 的全部内容, 来源链接: utcz.com/qa/262915.html