My problem is similar to Is it possible to have a relation where the foreign key is also the primary key? but I have to do this with Fluent API.
I have basically the same situation as described in the question, but I cannot use annotations on my domain models due to our coding standards. Here is a bit of code (Clarified):
Domain Classes:
public class Table1
{
public long ID { get; set; }
public int SubTableType { get; set; }
...
public Table2 Table2 { get; set; }
public Table3 Table3 { get; set; }
public List<Table4> Table4s { get; set; }
public List<Table5> Table5s { get; set; }
}
public class Table2
{
public long ID { get; set; }
public string Location { get; set; }
public string Task { get; set; }
...
public Table1 Table1 { get; set; }
public Table6 Table6 { get; set; }
public List<Table7> Table7s { get; set; }
}
public class Table3
{
public long ID { get; set; }
public string DescriptionAndLocation { get; set; }
...
public Table1 Table1 { get; set; }
}
Configuration Classes:
internal class Table1Configuration : EntityTypeConfiguration<Table1>
{
public Table1Configuration()
{
ToTable("Table1");
HasKey(so => so.ID);
Property(so => so.SubTableType)
.IsRequired();
Property(so => so.ID)
.IsRequired()
.HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity);
...
}
}
internal class Table2Configuration : EntityTypeConfiguration<Table2>
{
public Table2Configuration()
{
ToTable("Table2");
HasKey(bc => bc.ID);
Property(bc => bc.ID)
.IsRequired();
Property(bc => bc.Location)
.IsOptional()
.HasColumnType("nvarchar")
.HasMaxLength(50);
Property(bc => bc.Task)
.IsOptional()
.HasColumnType("nvarchar")
.HasMaxLength(4000);
...
HasRequired(bc => bc.Table1)
.WithOptional(so => so.Table2);
HasRequired(bc => bc.Table8)
.WithMany(bot => bot.Table2s)
.HasForeignKey(bc => bc.Tabe8ID);
}
}
internal class Table3Configuration : EntityTypeConfiguration<Table3>
{
public Table3Configuration()
{
ToTable("Table3");
HasKey(hic => hic.ID);
Property(hic => hic.DescriptionAndLocation)
.IsOptional()
.HasColumnType("nvarchar")
.HasMaxLength(4000);
Property(hic => hic.ID)
.IsRequired()
.HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity);
HasRequired(hic => hic.Table1)
.WithOptional(so => so.Table3);
}
}
When I run this code I get the error:
Invalid column name 'Table2_ID'.
I would try something like this:
modelBuilder.Entity<Table1>().HasKey(t => t.ID);
modelBuilder.Entity<Table1>().Property(t =>t.ID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<Table1>()
.HasOptional(t1 => t1.Table2)
.WithRequired(t2 => t2.Table1).Map(m => m.MapKey("ID"));
What you are asking is the so called Shared Primary Key Associations , which is the standard (and better supported) EF6 model for one-to-one relationships.
Rather than removing the ID
property, you should remove the MapKey
call which is used to define a shadow FK property (which you don't need).
Since the property called ID
by convention is a PK and required, basically all you need is this:
HasRequired(hic => hic.Table1)
.WithOptional(so => so.Table2); // or Table3
or the explicit equivalent of [Key]
/ [ForeignKey]
combination:
HasKey(hic => hic.ID);
HasRequired(hic => hic.Table1)
.WithOptional(so => so.Table2); // or Table3
Exactly as the example for Configuring a Required-to-Optional Relationship (One-to–Zero-or-One) from the documentation.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.