AspNetUsers’ ID as Foreign key in separate table, one-to-one relationship

I have looked up and down, tried all the different and various ways of being able to store a foreign key of the AspNetUser table in a separate Customer table. I’m still new at ASP.NET and the Entity Framework, but I’ve read quite a few posts and documentations.

Currently this is what I have

MODELS

public class Customer
{
    [Display (Name="Customer ID")]
    public int CustomerID { get; set; }

    public string UserId { get; set; }
    [ForeignKey("UserId")]
    public virtual ApplicationUser ApplicationUser { get; set; }

}


 public class ApplicationUser : IdentityUser
{
    public virtual Customer Customer { get; set; }
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public DbSet<Customer> Customers { get; set; }

    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }

}

I get this error, quote

Unable to determine the principal end of an association between the types ‘TestApplication.Models.Customer’ and ‘TestApplication.Models.ApplicationUser’. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

I also tried this person’s method found here: The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations

So I commented out the ForeignKey annotations and used the person’s suggestion, using the “modelBuilder” approach. And when I updated my database, the ‘Id’ from the AspNetUsers table was in the Customers table (which is good), but the CustomerID as a ForeignKey was also in the AspNetUsers table, which is not what I want.

What I want, is the AspNetUsers’ ‘Id’ to be in the Customers table as a ForeignKey.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

In a one-to-one relation the “child” table, in your case Customer, should have the same primary key as the related table, i.e. the foreign key.

The code sample you have supplied means that, in Customer you will have a PK named CustomerID which is different from UserId.

This should work in your case (untested):

public class Customer
{
    [Key]
    public string UserId { get; set; }

    [ForeignKey("UserId")]
    public virtual ApplicationUser ApplicationUser { get; set; }
}

public class ApplicationUser : IdentityUser
{
    public virtual Customer Customer { get; set; }
}

Edit:

MSDN for ForeignKeyAttribute states:

If you add the ForeigKey attribute to a foreign key property, you
should specify the name of the associated navigation property. If you
add the ForeigKey attribute to a navigation property, you should
specify the name of the associated foreign key(s).

I interpret this as that it should be possible to add the ForeignKey-attribute to either the navigation property or the foreign key property, and that either way should work, but apparently not. Moving it as per below should do the trick.

public class Customer
{
    [Key, ForeignKey("ApplicationUser")]
    public string UserId { get; set; }
    public virtual ApplicationUser ApplicationUser { get; set; }
}

public class ApplicationUser : IdentityUser
{
    public virtual Customer Customer { get; set; }
}

Method 2

I know this post is 2 years old, but a better solution would be to use Fluent API to set the foreign key (rather than using [ForeignKey] attribute in your Customer class. Here is how you would do it:

public class Customer
{
    public int CustomerID { get; set; }
    public virtual ApplicationUser ApplicationUser { get; set; }
}

public class ApplicationUser : IdentityUser
{
    public virtual Customer Customer { get; set; }
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext() : base("DefaultConnection")
    {
    }

    public DbSet<Customer> Customers { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // one-to-zero or one relationship between ApplicationUser and Customer
        // UserId column in Customers table will be foreign key
        modelBuilder.Entity<ApplicationUser>()
            .HasOptional(m => m.Customer)
            .WithRequired(m => m.ApplicationUser)
            .Map(p => p.MapKey("UserId"));
    }

}

This would create a UserId column in your Customers table that is a foreign key to AspNetUsers table. You can omit .Map(p => p.MayKey("UserId")) and EF will name the foreign key ApplicationUser_Id by convention.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x