简体   繁体   中英

EF core 2 composite primary key using Id and a foreign key

I have two model classes

    public class ClassA 
    {
        public Guid Id { get; set; }        

        public IEnumerable<ClassB> ClassBs { get; set; }

    }

    public class ClassB 
    {
        public String Id { get; set; }                

    }

How do I tell entity framework to create table ClassB with a composite primary key with ClassA.Id and ClassB.Id? That way I can have multiple records with the same Id in ClassB table. I don't want to change ClassB to add another Guid Id property. I don't want to use EF attributes either, I'd like to keep the model class separated from the ORM framework.

Write your ClassB as follows:

public class ClassB 
{
    public String Id { get; set; }

    public Guid ClassAId {get; set;}

    ...............

    public ClassA ClassA  {get; set;}               

}

Then write the ClassB Configuration as follows:

public class ClassBConfiguration : IEntityTypeConfiguration<ClassB>
{
    public void Configure(EntityTypeBuilder<ClassB> builder)
    {
        builder.HasKey(b => new { b.Id, b.ClassAId });

        builder.HasOne(b => b.ClassA).WithMany(a => a.ClassBs).HasForeignKey(b => b.ClassAId);
    }
}

Then in the OnModelCreating as follows:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
        base.OnModelCreating(modelBuilder);

        modelBuilder.ApplyConfiguration(new ClassBConfiguration());
}

If you don't want to introduce explicit FK property to ClassB model, you can utilize the non lambda overload of HasKey receinving string property names and pass the shadow FK property name, which by convention for this model is "ClassAId":

modelBuilder.Entity<ClassB>()
    .HasKey("Id", "ClassAId");

One of the drawbacks of this method is the usage of "magic" strings. But it can be avoided with the help of nameof operator.

Another drawback is that the only way to retrieve/manipulate ClassB objects would be through parent ClassA object (although inside EF Core LINQ to Entities queries you can use EF.Property<Guid>(param, "ClassAId") to access it for filtering/ordering/projection if needed).

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