Entity framework 外键属性是否可以是复合主键的一部分?

Entity framework 外键属性是否可以是复合主键的一部分?,entity-framework,entity-framework-6,code-first,foreign-key-relationship,composite-primary-key,Entity Framework,Entity Framework 6,Code First,Foreign Key Relationship,Composite Primary Key,遵循TPC模式。 我有一个名为Entity的抽象类,它由Person和LegalEntity继承 public abstract class Entity { public int Id { get; set; } } public class LegalEntity : Entity { public string CorporateName { get; set;} } public class Person : Entity { pub

遵循TPC模式。 我有一个名为Entity的抽象类,它由Person和LegalEntity继承

public abstract class Entity
  {
    public int Id { get; set; }
  }

public class LegalEntity : Entity
  {
     public string CorporateName { get; set;}
  }

public class Person : Entity
  {
      public string Name { get; set; }
  }
我还有另一个叫代理的,有很多孩子。为了简化,我将只显示一个类订户

public  abstract class Agent
  {
    public int EntityId { get; set; }

    public int RoleId { get; set; }
  }

 public  class Subscriber : Agent
  {
    public string Number { get; set; }
    
    public Entity Entity { get; set; } // No EntityId here because the foreign key correspond to the Id of Subscriber
  }
下面是我的实体的配置:

public AgentConfiguration()
    {
        HasKey(s => new { s.EntityId, s.RoleId });
        ...
    }

public SubsbcriberConfiguration()
   {
       Map(m =>
            {
               m.MapInheritedProperties();
               m.ToTable("T_ACTEUR_SOUSCRIPTEUR");
             }
         
            **.WithMany() //I don't want a property on the other side 
          .HasForeignKey(s => s.EntityId); // EF doesn't accept to put the property Id as a foreign key.**

   }

    public EntityConfiguration()
    {
        HasKey(e => e.Id);
        Property(e => e.Id).HasColumnName("id_personne");
        ...
     }

    public PersonConfiguration()
    {
        Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("T_PERSONNE_PHYSIQUE");
        });
     }
我在抽象类实体和具体类订户之间有一对一的关系。 类实体的主键同时是订阅者的复合主键和外键的一部分

是否可以配置此方案?

当我将属性Id声明为外键时,EF抛出如下异常:

  public SubsbcriberConfiguration()
    {
        HasKey(s => new { s.EntityId, s.RoleId });
        Property(s => s.EntityId).HasColumnName("id_personne")
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        Property(s => s.RoleId).HasColumnName("id_role")
             .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        ...
        ToTable("T_ACTEUR_SOUSCRIPTEUR");
        
        HasRequired(s => s.Entity)
         .WithMany()
         .HasForeignKey(s => s.EntityId)
         .WillCascadeOnDelete(false);
    }
外键组件“EntityId”不是类型“Subscriber”上声明的属性。验证它是否未从模型中明确排除,并且它是一个有效的基元属性

我尝试了许多方案,但没有找到解决方案,因为我有一对一的关系,但表有不同的键,外键是复合主键的一部分

如何首先在代码中将属性配置为外键和复合主键的一部分

我错过了什么?任何帮助都将不胜感激

编辑: 我打破了类代理和TPC的继承。现在,类订阅服务器没有父级。当我像下面这样配置它时:

  public SubsbcriberConfiguration()
    {
        HasKey(s => new { s.EntityId, s.RoleId });
        Property(s => s.EntityId).HasColumnName("id_personne")
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        Property(s => s.RoleId).HasColumnName("id_role")
             .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        ...
        ToTable("T_ACTEUR_SOUSCRIPTEUR");
        
        HasRequired(s => s.Entity)
         .WithMany()
         .HasForeignKey(s => s.EntityId)
         .WillCascadeOnDelete(false);
    }
实体框架正在寻找另一个外键:列Extent1.Entity\u Id不存在

当我尝试加载订阅服务器时,EF生成的查询是:

`SELECT 
   "Extent1"."id_personne",
   "Extent1"."id_role",
    ...
   "Extent1"."Entity_Id"
 FROM "T_ACTEUR_SOUSCRIPTEUR" AS "Extent1"
 WHERE "Extent1"."id_personne" = ((73660)) AND 
   "Extent1"."id_role" = ((4))`
我不知道如何向EF解释外键属性EntityId就是外键

有人能解释一下吗


谢谢。

嗯,我不确定我是否理解您的场景,但这可能会有所帮助

实体:

public class Entity
{
    public int EntityId { get; set; }
}

public abstract class Agent
{
    public int EntityId { get; set; }

    public int RoleId { get; set; }
}

public class Subscriber : Agent
{
    public string Number { get; set; }

    public Entity Entity { get; set; }
}
映射:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Entity>()
        .HasKey(e => e.EntityId);

    //map the Subscriber, not the Agent
    modelBuilder.Entity<Subscriber>()
        .HasKey(a => new { a.EntityId, a.RoleId });

    modelBuilder.Entity<Subscriber>()
        .HasRequired(i => i.Entity)
        .WithMany()
        .HasForeignKey(i => i.EntityId)
        .WillCascadeOnDelete(false);         

    base.OnModelCreating(modelBuilder);
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.HasKey(e=>e.EntityId);
//映射订阅服务器,而不是代理
modelBuilder.Entity()
.HasKey(a=>new{a.EntityId,a.RoleId});
modelBuilder.Entity()
.HasRequired(i=>i.Entity)
.有很多
.HasForeignKey(i=>i.EntityId)
.WillCascadeOnDelete(假);
基于模型创建(modelBuilder);
}
请注意,这是一种“一对多”关系,而不是一对一关系。您在评论中发布的文章使用独特的约束来“模拟”1:n关系中的1:1关系。我认为这不是一个好办法

但是,让我们假设您希望按照这种方式操作。您将把唯一约束放在哪里?FK是复合PK的一部分。如果你把一个唯一的约束放在那里,它会打破PK

考虑到PK由两列组成,而FK由PK的一列组成,我不认为真正的1:1关系是可能的。因为要具有1:1关系,FK列必须与PK列相同


希望有帮助

实体和订户的关系是“一对一”或“一对多”
WithMany()
用于1:nrelationships@FabioLuz在实体框架中,当实体之间有一对一的关系,并且有不同的键时,您必须遵循这种技巧,它也被称为“一对一外键关联”。看这个。如果我有相同的密钥,我会使用hasRequiRed()。WithOptional()技术…实体代理没有自己的Id,它有类实体的Id。它只是属性的名称。我编辑了答案。请检查。实体框架不了解Anthant,并且属性EntityId是实体的外键,我有以下例外:外键组件“EntityId”不是类型“Subscriber”上声明的属性。验证它是否没有被明确地从模型中排除,并且它是一个有效的基元属性。我已经更改了实体。请参阅答案我认为您不能先用代码将属性配置为外键和复合主键的一部分:-(