Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Foreign Key To Microsoft.AspNet.Identity.EntityFramework.IdentityUser?

I'm in VS 2013 and have just created an MVC application.

I'm creating an object I intend to have a foreign key to the AspNetUsers table in the resulting database. The project does have an ApplicationUser (deriving from IdentityUser) that looks like a property-column match with the AspNetUsers table.

How do we properly declare a foreign key to this?

public MyObject
{
   public string UserId { get; set; }

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

   // other properties
}

Now, I modify ApplicationUser to have a collection of MyObjects:

public ApplicationUser : IdentityUser
{
     public virtual ICollection<MyObject> MyObjects { get; set; }    
}

This seems to be how to do one-to-many in EF Code First. However, when I update-database, I'm getting the errors that say Identity members (IdentityUserLogin, IdentityUserRole, etc.) have no keys defined. Perhaps those classes were not meant to participate in EF Code First Migrations?

I could go "to the back" and add the foreign key via SQL statements, but if I wanted to update again from Code First, I might get errors (that the database doesn't currently match the older migration or something like that).

How do we properly foreign-key reference those membership tables?

I also tried to create an AspNetUser class with matching properties of the AspNetUsers table. Instead of "public ApplicationUser" on the Client class, I declared "public AspNetUser". Doing this resulted in a migration failure - "Automatic migration was not applied because it would result in data loss."

So, what to do?

like image 394
Mickael Caruso Avatar asked Nov 20 '13 18:11

Mickael Caruso


People also ask

What is Microsoft Aspnetcore identity UI?

ASP.NET Core Identity UI is the default Razor Pages built-in UI for the ASP.NET Core Identity framework. This package was built from the source code at https://github.com/dotnet/aspnetcore/tree/bb01bbf4433e27289b99001b7de6a582879d1835. Product. Versions. .NET.

What is IdentityDbContext?

IdentityDbContext() Initializes a new instance of the IdentityDbContext class. IdentityDbContext(DbContextOptions) Initializes a new instance of IdentityDbContext.

What is IdentityRole?

It contains default properties such as username, email, password e.t.c. This class can be inherited and more properties provided. IdentityRole is the ASP.NET Core MVC class that contains information about user roles (which are usage domains) of the IdentityUsers defined in your application.


2 Answers

It is easy to create a one-to-many relationship between ApplicationUser and MyObject and add a "UserId" foreign key in your MyObjects table. What I like about this solution is that it follows EF conventions and there is no need for [ForeignKey] attribute in your model:

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<MyObject> MyObjects { get; set; }
}

public class MyObject
{
    public int MyObjectId { get; set; }

    public string MyObjectName { get; set; }

    // other properties

    public virtual ApplicationUser ApplicationUser { get; set; }
}

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

    public DbSet<MyObject> MyObjects { get; set; }

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

        modelBuilder.Entity<MyObject>()
            .HasRequired(c => c.ApplicationUser)
            .WithMany(t => t.MyObjects)
            .Map(m => m.MapKey("UserId"));
    }
}

Notice the use of Fluent API to create a "UserId" foreign key in your MyObjects table. This solution would still work without adding the Fluent API, but then your foreign key column would be named "ApplicationUser_Id" in your MyObjects table by convention.

like image 118
kimbaudi Avatar answered Sep 27 '22 16:09

kimbaudi


I would do the following: In the ApplicationUser class, add a ForeignKey attribute,

public ApplicationUser : IdentityUser {
    [ForeignKey("UserID")]
    public virtual ICollection<MyCustomUser> MyCustomUsers{ get; set; }    
}

and in your model where you want to track to which user it belongs,

public MyObject {
    public string UserId { get; set; }

    // other properties
}

You don't need to store the whole ApplicationUser instance in the MyObject class, and the UserID will be generated automatically. It is important that is is of type string, as is the ID of the ApplicationUser!

like image 32
EluciusFTW Avatar answered Sep 27 '22 16:09

EluciusFTW