多重继承(也许是抽象 class?)C# Entity Framework

Multiple Inheritance (maybe Abstract class?) C# Entity Framework

过去几周,我一直致力于使用 Visual Studio 2015 在 c# 上开发基于 Entity Framework 6(代码优先)的数据库。

我目前正在处理继承提供的所有选项。 在这一点上,按照数据库的标准,我应该用主键实现多重继承。 这是什么意思? 这意味着我应该实现一个从另一个 class 继承的 class 并拥有自己的 PK 以识别他与父 class 不同。此时我可以使用 TPC 实现它,使父 class 抽象并且不在父上定义任何 PK。这是此时的代码示例(这有效并且我已经测试过)

    public abstract class Person
    {

        public string Name { get; set; }
        public string LastName { get; set; }

    }

    [Table("Students")]
    public class Student : Person
    {

        [Key]public int Id_student { get; set; }
        public string code_s { get; set; }
        public virtual ICollection<Course> courses { get; set; }

    }

然后我应该遵循的标准来构建我的数据库要求我实现另一个继承,以 Student 作为 Parent 并创建另一个继承自 Student 的 class。 我的第一个也是愚蠢的想法是让它像写

一样简单
ChildOfChild : Student

但显然没有用。

然后我想到了使 Student class Abstract 成为可能,但是当我声明 Student class Abstract 时,它并没有让我实例化它并为 table.我不确定是否有任何其他方法可以使用 abstract class 或任何其他可用于开发此方法的方法来执行此操作。 如果您不理解我正在尝试解决的问题,这就是我想要的代码示例。

    public abstract class Person
    {

        public string Name { get; set; }
        public string LastName { get; set; }

    }

    [Table("Students")]
    public class Student : Person
    {

        [Key]public int Id_student { get; set; }
        public string code_s { get; set; }
        public virtual ICollection<Course> courses { get; set; }

    }

    [Table("ExchangeStudent")]
    public class ExchangeStudent : Student
    {

        [Key]public int Id_exchange { get; set; }
        public string HomeUniversity {get; set;}

    }

您不能有两个主键。 StudentId_student 定义为主键,然后在 ExchangeStudent 中将 Id_exchange 定义为主键。我会在 Person 中实现 属性 'Id' 并删除 Id_studentId_exchange 属性。

    public abstract class Student : Person
    {
        [Key]public int Id_student { get; set; }        
    }

    public class LocalStudent : Student{

    }

    public class ExchangeStudent : Student
    {        
        public string HomeUniversity {get; set;}
    }

但我会考虑

public class Student : Person
    {

        [Key]public int Id_student { get; set; }
        public string code_s { get; set; }
        public virtual ICollection<Course> courses { get; set; }
        public ExchangeInfo ExchangeInfo{get;set;}
    }


    public class ExchangeInfo : Student
    {

        [Key]public int Id_exchange { get; set; }
        public Student Student{get;set;}
        public string HomeUniversity {get; set;}    
    }

HomeUniversity 听起来像学生的属性吗? 与单个 table 学生一起工作而不是从 2 table 中选择 2 个学生会更符合 table,以找出谁真正在听课 另外,您将如何为 table 开设 link 课程,例如面向两个 table 学生和 ExchangeStudent 的课程?

会有 Person 没有 Id 吗?如果没有,给一个Person一个Id属性。用你的流利语言定义 API 在你为 TPC 建模的地方,这个 Id 是你的学生和交换生的主键。

public class Person
{
    public int Id {get; set;
    public string Name { get; set; }
    public string LastName { get; set; }
}

public class Student : Person
{
    // the primary key is in the base class
    public string code_s { get; set; }
    public virtual ICollection<Course> courses { get; set; }
}

public class ExchangeStudent : Student
{
    // the primary key is in one of the base classes
    public string HomeUniversity {get; set;}
}

您的 DbContext 将 TPC 配置为 this link

class MyDbContext : DbContext
{
    public DbSet<Student> Students {get; set;}
    public DbSet<ExchangeStudent> ExchangeStudents {get; set;}

    protected override OnModelCreating(...)
    {   // configure Student and ExcahngeStudent as TPC,
        // if needed define primary key
        modelBuilder.Entity<Student>()
        .HasKey(student => student.Id)
        .Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Students");
        });

        modelBuilder.Entity<ExchangeStudent>()
        .HasKey(student => student.Id)
        .Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("ExchangeStudents");
        });
    }

我不确定是否需要 HasKey。因为主键跟在naming conventions之后,所以可能不需要。

使用 fluent API 以上属性的优点在于,它使您可以自由地在不同的数据库模型中使用相同的 类 和查询,只需指定不同的 DbContext。

根据我的理解,您需要两个 table,它们都具有自己的主键和外键来定义一对一关系。在您的 C# 代码中,您希望这些 table 具有继承关系。

我看到您使用 Entity Framework 执行此操作的唯一方法是拆分您的要求。首先创建代表您想要的 table 结构的数据库模型。

namespace DAO
{
    public abstract class Person
    {
        public string Name { get; set; }
    }

    public class Student
    {
        public int StudentId { get; set; }
        public string Nickname { get; set; }
    }

    //Use navigation property rather than inheritance to define the relationship
    public class ExchangeStudent 
    {
        public int ExchangeStudentId { get; set; }
        public string HomeUniversity { get; set; }
        public virtual Student Student { get; set; }
    }
}

这给了我以下代码:

 public override void Up()
        {
            CreateTable(
                "dbo.ExchangeStudent",
                c => new
                    {
                        ExchangeStudentId = c.Int(nullable: false, identity: true),
                        HomeUniversity = c.String(),
                        Student_StudentId = c.Int(),
                    })
                .PrimaryKey(t => t.ExchangeStudentId)
                .ForeignKey("dbo.Student", t => t.Student_StudentId)
                .Index(t => t.Student_StudentId);

            CreateTable(
                "dbo.Student",
                c => new
                    {
                        StudentId = c.Int(nullable: false, identity: true),
                        Nickname = c.String(),
                        Name = c.String(),
                    })
                .PrimaryKey(t => t.StudentId);

        }

现在如果您需要在 Student 和 ExchangeStudent 之间建立继承关系,您可以创建新对象以在不同的命名空间中定义

namespace BusinessObject
{
    public abstract class Person
    {
        public string Name { get; set; }
    }

    public class Student
    {
        public int StudentId { get; set; }
        public string Nickname { get; set; }
    }

    //ExchangeStudent derives from Student
    public class ExchangeStudent : Student
    {
        public int ExchangeStudentId { get; set; }
        public string HomeUniversity { get; set; }
    }
}

然后你只需要创建一个 class 来映射这两个对象。也有第 3 方库可以为您执行此操作。