分配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的值是有点麻烦,我敢肯定有做比这更好的方法。

  1. 而不是定义(ID = 0)的另一方法的脚手架,我使用的的FormCollection。您也可以使用[绑定(包括=“字段1,字段2,字段3”),以确保正确的字段被公布。
  2. 有很长的路由到登录用户UserId利用User.Identity.Name
  3. 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

回到顶部