Assigning UserId to Foreign Key = null

I am using Entity Framework 5 and MVC 4, with .NET 4.5, using First code migrations. I have foreign keys between two objects in a ratio of 1 to zero or -1. When I try to create a record for Jogger, everything explodes. I get error messages:

  • Foreign key is a null reference
  • dbo.Jogger does not exist
  • Unhandled exception ... no metadata.

When I launch EF Viewer, the navigation relationship is perfect. No Fluent API code is currently in use.

User class

[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; } 

Jogger class

  [ForeignKey("UserId")] public int JoggerId { get; set; } public virtual UserProfile UserId { get; set; } 

When the JoggerController is generated, it creates this code for the Get and Post methods:

 // 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); } 

In the Jogger / Create view, there are no fields for the JoggerId or UserId according to the generated code.

It usually doesn't work in the (ModelState.IsValid) part of the code, where Output shows JoggerId = 0 and UserId = null.

I did not see this behavior in the Contoso University tutorial on asp.net, and I also studied the MSDN Learn EF website. I can not solve this problem. Your advice is welcome.

+6
source share
3 answers

After much trial and error, I found a way to set the Foreign Key value to.

Firstly, my relationship was incorrectly established: UserProfile class does not need a public int? GolferId represents a navigation property. The final classes were as follows:

Userprofile

  [Key] [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] public int UserId { get; set; } public string UserName { get; set; } // Navigation properties public virtual Jogger Jogger { get; set; } 

Jogger class

 [Key] [ForeignKey("UserId")] public int JoggerId { get; set; } public string Pronation {get; set;} public virtual UserProfile UserId { get; set; } 

Establish the correct connection without the need for a Fluent API code.

Assigning a ForeignKey value was a bit more complicated, and I'm sure there are much better ways to do this than that.

  • Instead of another method for determining forests (id = 0), I used FormCollection. You can also use the [Bind (Include = "field1, field2, field3")] field to track the correct fields.
  • There is a long way to access the registered user, UserId, which uses User.Identity.Name
  • FormCollection allows me to reference and save other fields, for example. Pronation

     [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); } 

This was not at all true, but it really worked. Thanks @Moeri for pointing me in the right direction.

+3
source

Error in database model. Entity Framework Code First, configuration for one-to-one relationships is always required. Code. At first it is impossible to determine which class is dependent in these situations.

1- In the Jogger class, add the property:

 public virtual User User { get; set; } 

2 - In the OnModelCreating method add:

 protected override void OnModelCreating(DbModelBuilder modelBuilder) { // One to One relationship modelBuilder.Entity<User>() .HasOptional(t => t.Jogger) .WithOptionalDependent(m => m.User); } 
+2
source

Here is your mistake:

 public virtual UserProfile UserId { get; set; } 

Entity Framework Code First works with conventions, one of which is name-based conventions. This means that if you have the "UserId" property, it will look for the "User" table and configure it as a foreign key for this table. I think this exploded because you gave your navigation object a name, which is commonly used for a foreign key property.

The correct way to work:

 public virtual int? UserId { get; set; } public virtual User User { get; set; } 

If you want your property to be called "UserProfileId", you will need to use the "ForeignKey" attribute or the free configuration syntax so that the Entity Framework knows that it is a foreign key:

 public virtual int? UserProfileId{ get; set; } [ForeignKey("UserProfileId") public virtual User User { get; set; } 

or with smooth syntax (you write this in the OnModelCreating method of your Context or in a separate class that inherits from EntityTypeConfiguration):

 HasRequired(j => j.User).WithMany().HasForeignKey(i => i.UserProfileId) 

Edit: I just noticed that your User table is actually called UserProfile, which makes the second half of my answer controversial. However, I will leave it as it may be educational.

+1
source

Source: https://habr.com/ru/post/950889/


All Articles