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?
It is easy to create a one-to-many relationship between
ApplicationUser
andMyObject
and add a "UserId" foreign key in yourMyObjects
table. What I like about this solution is that it follows EF conventions and there is no need for[ForeignKey]
attribute in your model: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 yourMyObjects
table by convention.The ASP.NET Identity classes doesn't use attributes to define the relations, they expect the relations to be configured by the DbContext.
The default DbContext used with ASP.NET Identity,
IdentityDbContext<TUser>
includes the configuration. So if you make your DbContext class inherit fromIdentityDbContext<ApplicationUser>
you should be all set.Update
If you still get error: "Automatic migration was not applied because it would result in data loss." then do:
If you still get error messages about IdentityUserLogin, IdentityUserRole, etc. have no keys defined then you most likely are overriding the
OnModelCreating
method in your DbContext without calling the base method first. Add a call to the base like this:End of Update
If you don't want to inherit from
IdentityDbContext
you need to add some configuration for the Identity classes. One way to do this is by overridingOnModelCreating
. This is whereIdentityDbContext<ApplicationUser>
configure the entity framework mappings. If you add this to your DbContext class it should set up the mappings you need.I think you have it backwards. Maybe try something like:
I'm going from memory here so I might be a little off. Anyway, the important things is to have your EF user class inherit from IUser.
I would do the following: In the
ApplicationUser
class, add aForeignKey
attribute,and in your model where you want to track to which user it belongs,
You don't need to store the whole
ApplicationUser
instance in theMyObject
class, and theUserID
will be generated automatically. It is important that is is of typestring
, as is theID
of theApplicationUser
!