使用ID和外键的EF core 2复合主键

时间:2019-09-16 00:54:24

标签: c# .net-core entity-framework-core

我有两个模型课

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

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

    }

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

    }

如何告诉实体框架使用带有ClassA.Id和ClassB.Id的复合主键创建表ClassB?这样,我可以在ClassB表中具有相同ID的多个记录。 我不想更改ClassB来添加另一个Guid Id属性。我也不想使用EF属性,我想将模型类与ORM框架分开。

2 个答案:

答案 0 :(得分:0)

编写您的ClassB如下:

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

    public Guid ClassAId {get; set;}

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

    public ClassA ClassA  {get; set;}               

}

然后按如下所示编写ClassB配置:

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);
    }
}

然后在OnModelCreating中进行如下操作:

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

        modelBuilder.ApplyConfiguration(new ClassBConfiguration());
}

答案 1 :(得分:0)

如果您不想在ClassB模型中引入显式FK属性,则可以利用HasKey的非lambda重载来接收string属性名称并传递{{3} } FK属性名称,按照惯例,该模型的名称为“ ClassAId”:

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

此方法的缺点之一是使用“魔术”字符串。但是可以借助nameof运算符来避免。

另一个缺点是,检索/操作ClassB对象的唯一方法是通过父ClassA对象(尽管在EF Core LINQ to Entities查询中,您可以使用EF.Property<Guid>(param, "ClassAId")来访问它)用于过滤/排序/投影(如果需要)。