简体   繁体   English

多重继承(也许是抽象类?)C#实体框架

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

The last weeks I have been working on the development of a database based on Entity Framework 6 (Code-First) on c# using Visual Studio 2015. 最近几周,我一直在使用Visual Studio 2015在c#上基于Entity Framework 6(代码优先)开发数据库。

I'm currently working on all the options that inheritance offers to work with. 我目前正在处理继承提供的所有选项。 At this point and following the standards of a database I should implement multiple inheritance with Primary Key. 在这一点上,并按照数据库的标准,我应该使用主键实现多重继承。 What this means? 这是什么意思 This means that I should implement a class that inherits from another class and have his own PK for identify him different from the parent class. 这意味着我应该实现一个从另一个类继承的类,并具有自己的PK来识别与父类不同的他。 At this point I could implement it with TPC, making the parent class abstract and not defining any PK on the parent. 在这一点上,我可以用TPC来实现它,使父类成为抽象类,而不在父类上定义任何PK。 This is a sample of the code at this point (this works and I have tested it) 这是此时的代码示例(此方法有效,并且我已经对其进行了测试)

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

    }

Then the standard I should follow to build my database requires me to implement another inheritance taking Student as the Parent and creating another class that inherits from Student. 然后,我应该遵循的建立数据库的标准要求我实现另一个继承,以Student为父级,并创建另一个继承自Student的类。 The first and stupid idea I had was to make it as simple as write 我第一个愚蠢的想法是使其变得像编写一样简单

ChildOfChild : Student

But obviously it didn't work. 但是显然它没有用。

Then it come to my mind the possibility of make Student class Abstract, but when I declared the Student class Abstract it didn't let me instantiate it and seed the table. 然后我想到了使Student类成为Abstract的可能性,但是当我声明Student类Abstract时,它没有让我实例化它并为表添加种子。 I'm not sure if there is any other way to do this, using abstract class or any other method that could be useful to develop this. 我不确定是否有其他方法可以使用抽象类或任何其他对开发此方法有用的方法来执行此操作。 If you didn't understand the problem I'm trying to solve this is the sample of code that I would like to have and works. 如果您不了解该问题,那么我将尝试解决这是我希望拥有并可以正常工作的代码示例。

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

    }

You can't have two primary keys. 您不能有两个主键。 Student defines Id_student as primary key and then in ExchangeStudent you define Id_exchange as primary key. StudentId_student定义为主键,然后在ExchangeStudent Id_exchange定义为主键。 I would implement a property 'Id' in Person and get rid of the Id_student and Id_exchange properties. 我将在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;}
    }

but i would think about something like 但我会考虑类似

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

Can HomeUniversity sounds like an attribute of student? HomeUniversity听起来像学生的属性吗? it will be more confortable to work with single table of student instead of making 2 selects from 2 tables, to find out who is really listening cources also how you will create link for tables like course to two tables Student and ExchangeStudent? 与使用单个学生表而不是从2个表中进行2个选择相比,将更加舒适,以找出谁真正在聆听课程,以及如何为课程表(如课程表)创建两个表Student和ExchangeStudent的链接?

Will there be any Person that doesn't have an Id ? 会不会有什么Person不具有的Id If not, give a Person an Id property. 如果没有,给予PersonId属性。 Define in your fluent API where you model the TPC that this Id is the primary key of your Students as well as your exchange students. 定义你的流利的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;}
}

Your DbContext configures TPC as in this link 你的DbContext配置TPC在这个环节

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

I'm not sure if HasKey is needed. 我不知道如果HasKey是必要的。 Because the primary key follows the naming conventions , it might be that it is not needed. 因为主键下面的命名约定 ,这可能是不需要的。

The advantage of using fluent API above the use of attributes is that it gives you freedom to use the same classes and queries in a different database model, just by specifying a different DbContext. 使用属性的使用上面流畅API的优势在于,它给你的自由只是通过指定不同的DbContext使用相同的类和查询在不同的数据库模型。

From my understanding you want two tables where both with their own primary keys and a foreign key to define a one to one relationship. 根据我的理解,您希望两个表都具有各自的主键和一个外键来定义一对一关系。 In your C# code you want these tables to have an inheritance relationship. 在您的C#代码中,您希望这些表具有继承关系。

The only way I can see you doing this with Entity Framework is to split your requirements. 我看到您使用Entity Framework进行此操作的唯一方法是拆分您的需求。 Firstly create the Database models that represent the table structure you want. 首先创建代表您想要的表结构的数据库模型。

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

This gave me the following code: 这给了我以下代码:

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

        }

Now if you need to have a inheritance relationship between Student and ExchangeStudent you can create new objects to define in a different namespace 现在,如果您需要在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; }
    }
}

Then you just need to create a class that maps the two objects. 然后,您只需要创建一个映射两个对象的类。 There are 3rd party libraries that can do this for you as well. 也有第三方库可以为您执行此操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM