Foreign Key To Microsoft.AspNet.Identity.EntityFramework.IdentityUser?
Solution 1
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.
Solution 2
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
!
Solution 3
public MyObject
{
.. other properties
[MaxLength(128), ForeignKey("ApplicationUser")]
public virtual string UserId { get; set; }
public virtual ApplicationUser ApplicationUser { get; set;}
}
Mickael Caruso
Enthusiast Programmer working in mostly C#, the .net Framework, SQL Server, Flex/Actionscript, and (new to) Android.
Updated on June 04, 2022Comments
-
Mickael Caruso almost 2 years
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?
-
Mickael Caruso over 10 yearsI'm not trying to inherit MyCustomUser. I'm trying to have MyObject to have a foreign key to the ApplicationUser.
-
Mickael Caruso over 10 yearsI tried to inherit IdentityDbContext<ApplicationUser> - doesn't work. I still get the same error when I try to migrate.
-
Olav Nybø over 10 yearsUpdated my answer with some information on what to do depending on which error you get after making your DbContext inherit from the IdentityDbContext<ApplicationUser> class
-
Mickael Caruso over 10 yearsI got the error ".. result in lost data" when I created the AspNetUser class manually and included it in the migration. I also got that error when I overrode OnModelCreating with the 3 FK statements without inheriting IdentityDbContext<TUser>. When I inherited IdentityDbContext<TUser> as documentation states to do, I still get those "no keys defined" errors - I thought that IdentityDbContext<TUser> declared those keys, which would take care of everything.
-
Mickael Caruso over 10 yearsInterestingly, I just tried to start a new MVC project. The first thing I did was run Update-Database in the PM console. So I didn't create any new POCO objects or edit any existing models the project generated. I know there's the ApplicationDbContext already in there which inherited IdentityDbContext<TUser>. Running Update-Database gave me those validation errors where "has no keys defined." Microsoft may have taken those FK attributes out recently.
-
Cheung about 10 yearsI also try all possible solution of StackOverFlow, i also cannot set foreign key to the AspNetUsers table by Code-First, the new ASP.NET Identity is a joke.
-
ToastyMallows about 9 yearsWhat is the reason for the last line,
public virtual ApplicationUser ApplicationUser { get; set; }
? Shouldn't the ForeignKey to ApplicationUser in the line above that be sufficient? -
MichaelMao almost 8 yearsHow to achieve this by Fluent API?
-
kimbaudi over 7 years@MichaelMao - Please take a look at my solution on how to achieve this using Fluent API. Actually, you don't need Fluent API if you're happy with the foreign key name defaulting to "ApplicationUser_Id" by EF convention. However, if you want to customize the name of the foreign key, then it is necessary.
-
kimbaudi over 7 yearsI prefer to avoid using attributes to define EF relations as @BlackICE suggests and would avoid using
[ForeignKey]
. My solution uses Fluent API to define the relation, which I feel is much cleaner. Of course, the Fluent API is unnecessary if you want the foreign key to be named "ApplicationUser_Id" by convention. -
Daniel almost 4 years@ToastyMallows, the last line gives me a navigation property in linq queries. But you are right, leave it out and you will still get the foreign key.