C# 在不同于父类ID的子类(继承)上添加PK

C# 在不同于父类ID的子类(继承)上添加PK,c#,visual-studio,entity-framework,inheritance,ef-code-first,C#,Visual Studio,Entity Framework,Inheritance,Ef Code First,这些天来,我一直在使用实体Framwork 6(MVC、VisualStudio 2015、代码优先)进行继承。尝试不同的方面,我发现需要生成一个PrimaryKey来标识子类,与从父类继承的PrimaryKey/ForeignKey分开。 我想发展的想法是: public class Person { [Key] public int PersonId { get; set; } } public class Student : Person { [Key]

这些天来,我一直在使用实体Framwork 6(MVC、VisualStudio 2015、代码优先)进行继承。尝试不同的方面,我发现需要生成一个PrimaryKey来标识子类,与从父类继承的PrimaryKey/ForeignKey分开。 我想发展的想法是:

public class Person
{

    [Key]
    public int PersonId { get; set; }

}

public class Student : Person
{

    [Key]
    public int StudentId { get; set; }

}
我一直在寻找其他尝试过这个的人,但我什么也没找到。我不确定这是否可能,所以如果有人能帮助我,我会非常感激


谢谢。

如果你要描述一个
学生,你必须描述
学生.StudentId
学生.PersonId
的含义,你能给出一个正确的描述吗

在我看来,你想给学生一个主键的新属性的唯一原因是因为这个属性的标识符,而不是因为一个真正正确的含义

在实体框架中建模继承时应使用的方法取决于最常用的查询类型

假设你有三种类型的人:学生、老师和家长。考虑您最常做的查询类型:

  • 你最常问的是有……的学生,还是有……的家长
  • 或者你会经常为那些。。。很少有学生。。。或是那些
  • (1)主要要求学生…:使用TPC

    如果您将继承策略建模为,那么学生、教师和家长将各自拥有自己的表。没有通用的父表。学生拥有的所有父属性都在学生表中,类似的,所有这些父属性也都在教师表中

    这种继承策略是最好的,如果你主要要求学生谁。。。对于那些。。。使用TPC询问那些。。。我们只需要一张桌子。询问那些。。。将始终需要将查询结果连接到。。。老师们说。。。还有那些

    我发现这是我最常使用的继承策略

    (2)主要询问以下人员:使用TPT

    如果这些是最常用的查询,最好在单独的表中对所有人员数据进行建模,并让学生、教师和家长都对他们的人员数据有一些参考:

    如何实施TPC

    如果您根据TPC实现继承,那么就不会有单独的Person表。不需要给人身份证

    class Person
    {
        public string FirstName {get; set;}
        ...
    }
    
    class Student : Person
    {
        public int Id {get; set;}
        ...
    }
    
    class Teacher : Person
    {
        public int Id{get; set;
        ...
    }
    
    如果你计划从不实例化一个人,只有学生、老师和家长,那么就声明Person类抽象

    顺便说一下,如果您为主键属性指定默认名称
    Id
    ,entity framework将知道这应该是您的主键。不需要属性,也不需要fluent API

    在您的环境中:

    class MyDbContext : DbContext
    {
        public DbSet<Student> Students {get; set;}
        public DbSet<Teacher> Teachers {get; set;}
        public DbSet<Parent> Parents {get; set;}
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Student>().Map(student =>
            {
                student.MapInheritedProperties();
                student.ToTable(nameof(MyDbContext.Students));
            });
    
            modelBuilder.Entity<Teacher>().Map(teacher =>
            {
                teacher.MapInheritedProperties();
                teacher.ToTable(nameof(MyDbContext.Teachers));
            });
            // etc. for Parent
        }
    }
    

    但是,不确定您是否可以仅使用数据注释。。。。你为什么要这么做?有一个统一的PK名称是非常有用的。谢谢你的帮助!!最后实现了(2),我发现如果不在基类上声明PK,那么可以在子类中定义自己的PK。但是你不能用TPT实现这一点,你应该实现TPH
    class Person
    {
        public int Id {get;set;}
        ...
    }
    class Student
     {
        public int Id {get;set;}
        // A student has Person data via foreign key:
        public int PersonId {get; set;}
        public Person Person {get; set;}
        ...        
     }
     class Teacher
     {
        public int Id {get;set;}
        // A Teacher has Person data via foreign key:
        public int PersonId {get; set;}
        public Person Person {get; set;}
        ...        
     }