简体   繁体   中英

How to define a domain model where the Primary Key is also the Foreign Key with fluent api

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM