Reputation: 1504
I'm kinda new to Entity Framework and Code First Migration so I hope this is an easy question to answer. I am trying to create a one to one relationship between ApplicationUser (from ASP.NET identity) and Member. I have a Member class:
public class Member
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual Address Address { get; set; }
public UserStatus Status { get; set; }
public DateTime CreateDate { get; set; }
public virtual string ApplicationUserID { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
}
and an ApplicationUserClass:
public class ApplicationUser : IdentityUser
{
public ApplicationUser()
{
}
public virtual Member Member { get; set; }
}
In my DBContext (inherits IdentityDbContext)I have the following configuration:
modelBuilder.Entity<ApplicationUser>()
.HasOptional(t => t.Member).WithOptionalPrincipal();
base.OnModelCreating(modelBuilder);
When I run the code first migration, I'm getting this:
CreateTable(
"dbo.Members",
c => new
{
ID = c.Int(nullable: false, identity: true),
FirstName = c.String(),
LastName = c.String(),
Status = c.Int(nullable: false),
CreateDate = c.DateTime(nullable: false),
ApplicationUserID = c.String(maxLength: 128),
Address_ID = c.Int(),
ApplicationUser_Id = c.String(maxLength: 128),
})
.PrimaryKey(t => t.ID)
.ForeignKey("dbo.Addresses", t => t.Address_ID)
.ForeignKey("dbo.AspNetUsers", t => t.ApplicationUser_Id)
.ForeignKey("dbo.AspNetUsers", t => t.ApplicationUserID)
.Index(t => t.ApplicationUserID)
.Index(t => t.Address_ID)
.Index(t => t.ApplicationUser_Id);
Notice that I have 2 foreign keys, ApplicationUserID and ApplicationUser_Id. I want to try to do everything using FluentAPI (i.e. not Data Annotations). How would I configure it so that EF uses ApplicationUserID, the string ID I have in my class? I thought that Class+ID was the convention, so why is it creating another foreign key?
Upvotes: 0
Views: 1493
Reputation: 2776
I believe you should update your configuration this way:
modelBuilder.Entity<Member>()
.HasOptional(x => x.ApplicationUser)
.WithMany()
.HasForeignKey(x => x.ApplicationUserID);
This is the way EntityFramework treats one-to-one relationships, you have to map it that way and introduce UNIQUE
constraints over your DB table.
More information about this case is here: http://weblogs.asp.net/manavi/associations-in-ef-code-first-ctp5-part-3-one-to-one-foreign-key-associations
Here's the quote from the link:
The reason is simple: Code First (and EF in general) does not natively support one-to-one foreign key associations. In fact, EF does not support any association scenario that involves unique constraints at all. Fortunately, in this case we don’t care what’s on the target side of the association, so we can treat it like a to-one association without the many part. All we want is to express “This entity (User) has a property that is a reference to an instance of another entity (Address)” and use a foreign key field to represent that relationship. Basically EF still thinks that the relationship is many-to-one. This is a workaround for the current EF limitation which comes with two consequences: First, EF won't create any additional constraint for us to enforces this relationship as a one to one, we need to manually create it ourselves. The second limitation that this lack of support impose to us is more important: one to one foreign key associations cannot be bidirectional (i.e. we cannot define a User property on the Address class).
Upvotes: 2