I have been playing around with .NET Core for the past couple of weeks and decided to try EF Core (coming from ASP.NET MVC with NHibernate). After a bit of digging I found a nice extensions called EF Visual Designer. It allows me to visually create the model and generate code.
I have defined a simple one-to-one relationship shown in the diagram: Simple one-to-one relationship
After generating the code I get the following as Fluent API code:
modelBuilder.Entity<Authentication>()
.ToTable("Authentications")
.HasKey(t => t.Id);
modelBuilder.Entity<Authentication>()
.Property(t => t.Id)
.IsRequired()
.ValueGeneratedOnAdd();
modelBuilder.Entity<User>()
.ToTable("Users")
.HasKey(t => t.Id);
modelBuilder.Entity<User>()
.Property(t => t.Id)
.IsRequired()
.ValueGeneratedOnAdd();
modelBuilder.Entity<User>()
.HasOne(x => x.Authentication)
.WithOne()
.HasForeignKey("Authentication_Id")
.IsRequired();
The user class has the following (relevant) properties:
[Key]
[Required]
public Guid Id { get; set; }
...
public virtual Authentication Authentication { get; set; }
Authentication has the following (relevant) property:
[Key]
[Required]
public Guid Id { get; set; }
However when I try to generate a migration I get the following error:
You are configuring a relationship between 'User' and 'Authentication' but have specified a foreign key on 'Authentication_Id'. The foreign key must be defined on a type that is part of the relationship.
I tried switching to a many-to-one relationship and that works without any problems. That could be a work-around but not a very clean one. Is this perhaps due to naming issues like both entities having "Id" as primary key?
If that's the case, what is the "best practice"? Do I give every entity a unique ID-column name? How do I go about an abstract entity with derived classes all inheriting the ID column?
I have never used EF Visual Designer to generate codes but just by looking at your code, either the User
entity needs the foreign key of Authentication
, or Authentication
entity needs the foreign key of User
.
Let's say you want to put the foreign key in User
:
public class User
{
[Key]
[Required]
public Guid Id { get; set; }
public Guid AuthenticationId { get; set; }
// Even this navigation property is optional
// for configuring one-to-one relationship
public virtual Authentication Authentication { get; set; }
}
public Authentication
{
[Key]
[Required]
public Guid Id { get; set; }
}
Then the one-to-one relationship should be configured as:
modelBuilder.Entity<User>()
.HasOne(x => x.Authentication)
// Or like this if you don't have Authentication navigation property:
//.HasOne<Authentication>()
.WithOne()
.HasForeignKey(x => x.AuthenticationId);
And no, you don't have to give every entity a unique ID-column name. In fact, you can call whatever in your code and rename it inside the configuration:
modelBuilder.Entity<User>()
.Property(x => x.Id).HasColumnName("WHATEVER_YOU_WANT_TO_CALL_IN_DB");
You need to put the foreign key on the other class. It looks like you don't have a property "Authentication_Id" on the Authentication class.